Bagaimana cara menyelaraskan semua teks dalam CSS secara vertikal?

12

Masalah ini tampaknya bahwa surat-surat tertentu seperti g, y, q, dll yang memiliki ekor yang lereng bawah, tidak memungkinkan untuk centering vertikal. Berikut ini gambar untuk menunjukkan masalahnya Sebuah.

Karakter dalam kotak hijau pada dasarnya sempurna, karena mereka tidak memiliki ekor ke bawah. Mereka yang berada di kotak merah menunjukkan masalahnya.

Saya ingin semua karakter berpusat secara vertikal sempurna. Dalam gambar, karakter dengan ekor ke bawah tidak di tengah secara vertikal. Apakah ini mungkin diperbaiki?

Ini biola yang menunjukkan masalah secara penuh .

.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>

Tas Chron
sumber
1
Ini pertanyaan yang menarik. Jawabannya mungkin ada di sini: iamvdo.me/en/blog/…
dwjohnston
2
dalam hal ini Anda perlu menentukan apa pusatnya . Bagi saya y sebenarnya berpusat dan A mungkin tidak. jangan bicara ketika kita memiliki font-family yang berbeda, penyelarasan akan semakin buruk
Temani Afif
1
Begitulah cara surat bekerja. Mereka disejajarkan, karena bagian vdalam ydan obagian dalam gberada pada baris yang sama dengan titik terendah untuk huruf kapital. Dengan logika Anda, Å, Ä, Ö akan disejajarkan seperti A dan O tetapi tidak bisa. Jika Anda ingin melakukan sesuatu yang istimewa tentang itu, Anda perlu menggunakan javascript untuk memeriksa apakah itu cap kecil dan kemudian mendorong karakter hingga beberapa karakter.
Rickard Elimää
1
Saya ingin tahu apakah ada jawaban yang berguna di sini. Masalahnya tampaknya bahwa ini benar-benar berpusat. yaitu. katakanlah Anda dapat memindahkan y dan g ke atas, bagaimana jika Anda memiliki huruf kecil a? bagaimana seharusnya tampilan itu?
dwjohnston
2
Buka font Anda di editor font apa saja. Edit setiap karakter sampai Anda puas dengan apa yang Anda lihat sebagai "terpusat" . Simpan dan gunakan sebagai keluarga font baru Anda. Seharusnya tidak lebih dari 15 menit. Saya tidak melihat cara lain selain SVG atau tipu daya lain menggunakan kanvas & co Tetapi saya akan memikirkan pertanyaan ini.
Roko C. Buljan

Jawaban:

4

Ini solusi saya menggunakan JS. Idenya adalah untuk mengubah elemen menjadi gambar untuk mendapatkan datanya sebagai piksel kemudian loop melalui mereka untuk menemukan bagian atas dan bawah setiap karakter dan menerapkan terjemahan untuk memperbaiki perataan. Ini akan bekerja dengan properti font dinamis.

Kode tidak dioptimalkan tetapi menyoroti gagasan utama:

MEMPERBARUI

Berikut ini adalah optimasi kode yang pertama:

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>

Saya menggunakan plugin dom-to-image untuk ini.

Temani Afif
sumber
Tungau berjalan lambat, tetapi ini adalah solusi pertama yang bekerja secara konsisten sejauh ini. (Dengan peringatan bahwa  yang berpusat pada teknis terlihat aneh.)
Brilliand
@Brilliand Saya secara eksplisit digunakan Âuntuk menunjukkan bahwa pemusatan dirinya tidak optimal seperti yang saya komentari dalam jawabannya;) Dia mungkin akan berubah pikiran setelah melihat ini dan menerima cara font bekerja
Temani Afif
Ini terlihat cukup bagus. Saya pikir saya akan menggunakan ini, jika saya bisa membuatnya lebih efisien. Saat ini sepertinya agak lambat.
Chron Bag
@ ChronBag ya Anda dapat bekerja pada kode dan mengoptimalkannya, ada ruang untuk ini. Saya tidak melakukannya karena saya butuh banyak waktu dan itu bukan tujuan dari pertanyaan. Saya ingin fokus pada ide utama. Mungkin akan dilakukan nanti.
Temani Afif
@ ChronBag menambahkan pengoptimalan, sedikit lebih cepat kurasa.
Temani Afif
1

Mungkin ada jawaban yang lebih baik, tetapi sepertinya satu-satunya cara adalah dengan menerapkan gaya yang berbeda secara manual tergantung pada apakah itu salah satu dari:

  • Huruf kapital
  • Huruf kecil dengan ekor
  • Huruf kecil dengan tangkai
  • Huruf kecil dengan keduanya

Sekarang perhatikan bahwa, dalam pemahaman saya, ketinggian relatif ekor dan tangkai saya pikir didefinisikan oleh font. Saya tidak yakin apakah ada cara untuk mengaksesnya secara terprogram - jadi Anda mungkin perlu menyesuaikan nilai-nilai ini dengan font.

Perhatikan juga bahwa solusi ini tidak akan berfungsi untuk mendukung banyak bahasa - karena Anda perlu menentukan kategori mana yang cocok untuk setiap karakter dalam berbagai set karakter yang berbeda.

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>

djohnston
sumber
Saya berharap untuk menghindari sesuatu seperti ini, tetapi mungkin itu satu-satunya solusi. Jika tidak ada yang datang, saya mungkin akan menggunakan ini. Terima kasih
Chron Bag
2
Jika surat itu bisa berupa huruf unicode (dari alfabet apa pun), maka ini menjadi tidak bisa dijalankan.
Brilliand
Anda lupa ÂËdanâë
Temani Afif
Ah ya, titik bagus @Brilli dan pengguna saya akan dapat menggunakan teks unicode untuk nama tampilan mereka, jadi solusi ini bahkan lebih rapuh.
Chron Bag
0

Ini situasi yang sulit!

Dari apa yang bisa saya katakan, ini akan paling sulit untuk membuat scalable secara native (yaitu %, vwatau vhnilai daripada pxatau em). Jika Anda perlu membuat ini terlihat cantik di ponsel atau tablet, harap pertimbangkan untuk menggunakan solusi saya dengan@media breakpoints.

Solusi saya pada dasarnya mendeteksi jika itu adalah elemen huruf kecil dengan ekor dan menambahkan kelas untuk mengimbangi ketinggian untuk mengimbangi ekor.

Dalam pengujian saya, itu tidak muncul bahwa setiap penangan tambahan diperlukan untuk modal huruf atau huruf kecil huruf tanpa ekor . Jangan ragu untuk mengoreksi saya jika saya salah.

Ada JSFiddle jika Anda ingin dipusingkan dan mengubah / menguji solusi ini.

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>

Biarkan saya tahu pikiran Anda dan jika saya melewatkan sesuatu. Ini akan keren untuk mendapatkan solusi akhir untuk ini karena saya sendiri pernah mengalami masalah serupa!

EGC
sumber
Ini tampaknya mirip dengan solusi dwjohnston, dan tunduk pada perangkap yang sama seperti miliknya. Namun demikian, ini dihargai, dan saya mungkin akan berakhir dengan sesuatu di sepanjang garis ini jika tidak ada yang lebih ideal datang.
Chron Bag
Saya kira sebagai upaya terakhir, Anda bisa menempuh jalur penghitungan piksel - seperti yang terlihat di sini di mana Anda akan mendeteksi ketinggian sebenarnya dalam piksel dan kemudian menerapkan offset yang sesuai.
EGC
1
Ya saya sebutkan ide itu di komentar ke OP. Mungkin itu cara untuk pergi.
Chron Bag
Maaf karena mencatat ide Anda lagi .. terlalu banyak komentar, jelas melewatkannya!
EGC
-1

Anda mungkin membutuhkan helperclass untuk ini, sehingga Anda dapat menerjemahkan huruf kecil lebih banyak dari huruf kapital. Sebuah skrip sederhana dapat dengan mudah menempatkan kelas pembantu ini secara otomatis.

Semoga ini bisa menyelesaikan masalah untuk Anda :)

.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>

Ragna Roaldset
sumber
Anda ytidak terpusat. Tweek lagi!
Roko C. Buljan
Saya juga tidak tahu sebelumnya apa surat-surat itu.
Chron Bag
Saya mengerti itu, tetapi sebuah skrip yang memeriksa apakah surat itu huruf besar atau kecil dan menempatkan helperclass pada HTML berdasarkan yang akan memperbaikinya dengan mudah :)
Ragna Roaldset
@RagnaRoaldset Saya pikir dia tidak bermaksud huruf besar atau kecil. Maksudnya ada huruf kecil namun bentuk karakternya berbeda. Bandingkan odan yAnda akan mendapatkannya. Karakter dengan ekor menciptakan masalah di tempat pertama (disebutkan dalam posting).
Anna
1
Anda selalu dapat membuat array untuk semua huruf dengan ekor, dan memutarnya untuk memeriksa apakah huruf dalam div cocok sebelum menerapkan kelas :) Tapi saya mengerti, hanya mencoba untuk datang dengan solusi :) harap seseorang datang dengan itu :)
Ragna Roaldset