Come allineare verticalmente tutto il testo nei CSS?


12

Il problema sembra essere che alcune lettere come g, y, q, ecc che hanno una coda che degrada verso il basso, non consentono la centratura verticale. Ecco un'immagine per mostrare il problema un'.

I personaggi nella casella verde sono sostanzialmente perfetti, in quanto non hanno una coda discendente. Quelli nel riquadro rosso dimostrano il problema.

Vorrei che tutti i personaggi fossero perfettamente centrati verticalmente. Nell'immagine, i personaggi con una coda verso il basso non sono centrati verticalmente. È possibile correggere questo?

Ecco il violino che dimostra il problema per intero .

.avatar {
    border-radius: 50%;
    display: inline-block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    top: 50%;
    transform: translateY(-50%);
    line-height: 100%;
    color: #fff;
}
<div class="avatar">
  <div class="character">W</div>
</div>

<div class="avatar">
  <div class="character">y</div>
</div>


1
Questa è una domanda interessante La risposta potrebbe essere qui: iamvdo.me/it/blog/…
dwjohnston

2
in questo caso è necessario definire qual è il centro . Per me la y è in realtà centrata e la A forse no. non parliamo quando abbiamo una famiglia di caratteri diversa, l'allineamento peggiorerà ancora
Temani Afif

1
È così che funzionano le lettere. Sono allineati, poiché la vin ye la oparte in gsono sulla stessa riga del punto più basso per le lettere maiuscole. Con la tua logica, Å, Ä, Ö verrebbero allineati come A e O ma non possono esserlo. Se vuoi fare qualcosa di speciale, devi usare javascript per verificare se si tratta di un maiuscolo e quindi spostare il carattere di alcuni caratteri.
Rickard Elimää,

1
Sono curioso di sapere se esiste una risposta utile qui. Il problema sembrerebbe essere che questi siano realmente centrati. vale a dire. dire che potresti spostare ye g in alto, e se avessi una a minuscola? come dovrebbe essere visualizzato?
dwjohnston,

2
Apri il tuo carattere in qualsiasi editor di caratteri. Modifica ogni personaggio fino a quando non sei soddisfatto di ciò che vedi come "centrato" . Salva e utilizza come nuova famiglia di caratteri. Non dovrebbe richiedere più di 15 minuti. Non vedo altro modo sano oltre a SVG o ad altri trucchi che usano canvas & co. Ma penserò a questa domanda.
Roko C. Buljan,

Risposte:


4

Ecco la mia soluzione usando JS. L'idea è di trasformare l'elemento in un'immagine al fine di ottenere i suoi dati come pixel, quindi scorrere attraverso di essi per trovare la parte superiore e inferiore di ciascun carattere e applicare una traduzione per correggere l'allineamento. Questo funzionerà con proprietà di carattere dinamiche.

Il codice non è ottimizzato ma evidenzia l'idea principale:

AGGIORNARE

Ecco una prima ottimizzazione del codice:

var elems = document.querySelectorAll(".avatar");
var k = 0;

for (var i = 0; i < elems.length; i++) {
  domtoimage.toPixelData(elems[i])
    .then(function(im) {
     var l = im.length;
      /* Search for the top limit */
      var t = 0;
      for (var j = 0; j < l; j+=4) {
          if (im[j+1] == 255) { /* Since we know the colors, we can only test the G composant */
            t = Math.ceil((j/4)/125);
            break;
          }
      }
      /* Search the bottom limit*/
      var b = 0;
      for (var j = l - 1; j >= 0; j-=4) {
          if (im[j+1] == 255) {
            b = 125 - Math.ceil((j/4)/125);
            break;
          }
      }
      /* get the difference and apply a translation*/
      elems[k].querySelector('.character').style.transform = "translateY(" + (b - t)/2 + "px)";
      k++;
    });
}
.avatar {
  border-radius: 50%;
  display: inline-flex;
  vertical-align:top;
  justify-content: center;
  align-items: center;
  width: 125px;
  height: 125px;
  font-size: 60px;
  background: 
    linear-gradient(red,red) center/100% 1px no-repeat,
    rgb(81, 75, 93);
  font-family: "Segoe UI";
  margin-bottom: 10px;
}

.character {
  color: #fff;
}
<script type="text/javascript" src="https://css-challenges.com/wp-content/themes/ronneby_child/js/dom-to-image.js"></script>
<div class="avatar">
  <div class="character">W</div>
</div>

<div class="avatar">
  <div class="character">y</div>
</div>

<div class="avatar">
  <div class="character" style="font-size:35px">a</div>
</div>

<div class="avatar">
  <div class="character" style="font-size:25px">2</div>
</div>
<div class="avatar">
  <div class="character">o</div>
</div>
<div class="avatar">
  <div class="character">|</div>
</div>
<div class="avatar">
  <div class="character">@</div>
</div>
<div class="avatar">
  <div class="character">Â</div>
</div>

<div class="avatar">
  <div class="character" style="font-family:arial">Q</div>
</div>
<div class="avatar">
  <div class="character">~</div>
</div>
<div class="avatar">
  <div class="character">8</div>
</div>

<div class="avatar">
  <div class="character">ä</div>
</div>
<div class="avatar">
  <div class="character">ç</div>
</div>

<div class="avatar">
  <div class="character">$</div>
</div>

<div class="avatar">
  <div class="character">></div>
</div>
<div class="avatar">
  <div class="character">%</div>
</div>

Per questo sto usando il plugin dom-to-image .


Un acaro a funzionamento lento, ma questa è la prima soluzione funzionante finora. (Con l'avvertenza che il  tecnicamente centrato sembra strano.)
Brilliand

@Brilliand Dimostravo esplicitamente Âche il suo centramento non è ottimale come ho commentato nella sua risposta;) Probabilmente cambierà idea dopo aver visto questo e accetterà il modo in cui il carattere funziona
Temani Afif

Questo sembra abbastanza buono. Penso che userò questo, se posso renderlo più efficiente. Attualmente sembra un po 'lento.
Chron Bag,

@ChronBag sì, puoi lavorare sul codice e ottimizzarlo, c'è spazio per questo. Non l'ho fatto perché mi ci vuole molto tempo e non è proprio lo scopo della domanda. Volevo concentrarmi sull'idea principale. Probabilmente lo farà più tardi a proposito.
Temani dopo il

@ChronBag ha aggiunto un'ottimizzazione, un po 'più veloce immagino.
Temani dopo il

1

Forse c'è una risposta migliore, ma sembra che l'unico modo per applicare manualmente stili diversi a seconda che si tratti di:

  • Lettera maiuscola
  • Minuscolo con una coda
  • Minuscolo con un gambo
  • Minuscolo con nessuno dei due

Ora nota che, secondo la mia comprensione, le altezze relative di code e steli penso che siano definite dal carattere. Non sono sicuro che esista un modo per accedervi in ​​modo programmatico, quindi potrebbe essere necessario modificare questi valori con il carattere.

Si noti inoltre che questa soluzione non funzionerebbe per il supporto di più lingue, in quanto è necessario definire in quale categoria ogni singolo personaggio rientra in dozzine di set di caratteri diversi.

const letters = ['a', 'b', 'y', 'X', 'c', 'y', 'A', 'B', 'Y']; 

function getAdditionalClass(char){
    //To do - fill arrays with the rest of the appropriate letters
    if (['y', 'g'].includes(char)) {
        return "tail"; 
    }
    if (['b', 'd'].includes(char)) {
        return "stalk"; 
    }
    
    if (['a', 'c'].includes(char)) {
        return "small"; 
    }
    
    return "capital"; 
}

letters.forEach(v => {
  const avatar = document.createElement("div"); 
  avatar.className = "avatar"; 
  const character = document.createElement("div");
  character.textContent = v; 
  character.className = `character ${getAdditionalClass(v)}`; 
  
  avatar.appendChild(character); 
  
  const root = document.getElementById("root"); 
  
  root.appendChild(avatar); 
  
});
.avatar {
    border-radius: 50%;
    display: block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    transform: translateY(-50%);
    line-height: 100%;
    color: #fff;
}


.small {
    top: 45%; 
}

.stalk {
    top: 50%;
}

.tail {
    top: 41%;
}

.capital {
    top: 50%;
}

#root {
    display: flex; 
    flex-flow: row wrap; 
}
<div id = "root">

</div>


Speravo di evitare qualcosa del genere, ma potrebbe essere l'unica soluzione. Se non succede nient'altro, probabilmente userò questo. Grazie
Chron Bag il

2
Se la lettera può essere qualsiasi lettera unicode (da qualsiasi alfabeto), allora ciò diventa inattuabile.
Brilliand,

Dimentichi il ÂËeâë
Temani dopo il

Ah sì, buon punto @Brilliand I miei utenti saranno in grado di utilizzare qualsiasi testo unicode per i loro nomi visualizzati, quindi questa soluzione è ancora più fragile.
Chron Bag,

0

Questa è una situazione difficile!

Da quello che posso dire, questo sarà più difficile da rendere nativamente scalabile (cioè %, vwo vhvalori invece di pxo em). Se hai bisogno di renderlo bello su cellulare o tablet, ti preghiamo di considerare di usare la mia soluzione con @mediapunti di interruzione.

La mia soluzione rileva essenzialmente se si tratta di un elemento minuscolo con una coda e aggiunge una classe per compensare l'altezza per compensare la coda.

Nel mio test, non sembra che gli eventuali gestori supplementari sono stati necessari per maiuscole lettere o minuscole lettere senza coda . Sentiti libero di correggermi se sbaglio.

C'è un JSFiddle se vuoi scherzare e cambiare / testare questa soluzione.

var circles = document.getElementsByClassName('circle');
var tails = ['q', 'y', 'p', 'g', 'j'] ;

Array.from(circles).forEach(render);
  
function render(element) { 		
    if(element.innerText == element.innerText.toLowerCase() &&
    	tails.includes(element.innerText)) {
    	element.className += " scale";
    }
}
.circle {
  height: 150px;
  width: 150px;
  background-color: #bbb;
  border-radius: 50%;
  display: inline-block;
  text-align: center;
  vertical-align: middle;
  line-height: 150px;
  font-size: 50px;
}

.scale {
  line-height: 135px;
}
<div>
  <div class="circle">W</div>
  <div class="circle">X</div>
</div>
<div>
  <div class="circle">y</div>
  <div class="circle">t</div>
</div>

Fammi sapere i tuoi pensieri e se mi sono perso qualcosa. Sarebbe bello ottenere una soluzione definitiva per questo dato che ho avuto problemi simili in passato!


Questo sembra essere simile alla soluzione di dwjohnston e soggetto alle stesse insidie ​​della sua. Tuttavia, è apprezzato, e potrei finire per andare avanti con qualcosa di simile se non arrivasse nulla di più ideale.
Chron Bag,

Suppongo che, come ultima risorsa, potresti percorrere il percorso del conteggio dei pixel - come visto qui per cui potresti rilevare la sua altezza effettiva in pixel e quindi applicare l'offset appropriato.
EGC

1
Sì, ho menzionato quell'idea nei commenti all'OP. Forse è questa la strada da percorrere.
Chron Bag,

Scusa se ho notato di nuovo la tua idea .. troppi commenti, ovviamente l'ho persa!
EGC

-1

Probabilmente avresti bisogno di un helperclass per questo, in modo da poter tradurre le lettere minuscole più delle lettere maiuscole. Un semplice script può facilmente attivare automaticamente queste classi di supporto.

Spero che questo risolva il problema per te :)

.avatar {
    border-radius: 50%;
    display: block;
    text-align: center;
    width: 125px;
    height: 125px;
    font-size: 60px;
    background-color: rgb(81, 75, 93);
    font-family: "Segoe UI";
    margin-bottom: 10px;
}

.character {
    position: relative;
    top: 50%;
    line-height: 100%;
    color: #fff;
}
.character-lowercase {
  transform: translateY(-60%);
}
.character-capital {
  transform: translateY(-50%);
}
<div class="avatar">
  <div class="character character-capital">W</div>
</div>

<div class="avatar">
  <div class="character character-lowercase">y</div>
</div>


il tuo ynon è centrato. Tweek altro!
Roko C. Buljan,

Inoltre, non so in anticipo quali saranno le lettere.
Chron Bag,

Lo capisco, ma uno script che controlla se la lettera è maiuscola o minuscola e mette un helperclass sull'HTML basato su quello risolverà facilmente :)
qualcuno

@RagnaRoaldset Penso che non significhi maiuscole o minuscole. Voleva dire che c'è una forma di carattere minuscola ma diversa. Confronta oe yotterrai questo. I personaggi con la coda creano il problema al primo posto (menzionato in post).
Anna,

1
Puoi sempre creare un array per tutte le lettere con la coda e scorrere attraverso di esso per verificare se la lettera nel div corrisponde prima di applicare la classe :) Ma ho capito, ho appena provato a trovare una soluzione :) spero che qualcuno trovi esso :)
qualcuno dal
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.