CSS'deki tüm metinler dikey olarak nasıl hizalanır?


12

Sorun gibi bazı harfler gibi görünüyor g, y, qyamaçları aşağı doğru dikey merkezleme için izin vermez bir kuyruk var, vb. İşte sorunu sergilemek için bir resim bir.

Yeşil kutudaki karakterler, aşağı doğru kuyrukları olmadığı için temelde mükemmeldir. Kırmızı kutudakiler sorunu göstermektedir.

Tüm karakterlerin mükemmel bir şekilde dikey olarak ortalanmasını istiyorum. Görüntüde, aşağı kuyruğu olan karakterler dikey olarak ortalanmamıştır. Bunu düzeltmek mümkün mü?

İşte sorunu tam olarak gösteren keman .

.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
Bu ilginç bir soru. Cevap burada olabilir: iamvdo.me/en/blog/…
dwjohnston

2
bu durumda merkezin ne olduğunu tanımlamanız gerekir . Benim için y aslında ortalanmış ve A belki değil. Farklı yazı tipi ailemiz olduğunda konuşmayalım, hizalama daha da kötüleşecek
Temani Afif

1
Harfler böyle çalışır. Çünkü, hizalanmış viçinde yve okısmen gbüyük harflerle için en düşük noktası olarak aynı hat üzerindedir. Mantıkınız Å, Ä, Ö ile A ve O gibi hizalanır, ancak olamazlar. Bu konuda özel bir şey yapmak istiyorsanız, küçük bir başlık olup olmadığını kontrol etmek için javascript kullanmanız ve ardından karakteri birkaç karakter yukarı itmeniz gerekir.
Rickard Elimää

1
Burada yararlı bir cevap olup olmadığını merak ediyorum. Sorun, bunların gerçekten ortalanmış olması gibi görünmektedir. yani. y ve g'yi yukarı taşıyabileceğinizi söyleyin, ya küçük harfiniz varsa a? bu nasıl olmalı?
dwjohnston

2
Yazı tipinizi herhangi bir yazı tipi düzenleyicisinde açın. "Ortalanmış" olarak gördüğünüz şeyden memnun olana kadar her karakteri düzenleyin . Kaydedin ve yepyeni font aileniz olarak kullanın. 15 dakikadan fazla sürmemelidir. SVG veya canvas & co kullanan diğer hilelerin dışında başka aklı başında bir yol göremiyorum. Ama bu soruyu düşüneceğim.
Roko C. Buljan

Yanıtlar:


4

İşte JS kullanarak benim çözüm. Fikir, verilerini piksel olarak almak için öğeyi bir görüntüye dönüştürmek, daha sonra her karakterin üstünü ve altını bulmak için hizalamak ve hizalamayı düzeltmek için bir çeviri uygulamaktır. Bu, dinamik yazı tipi özellikleriyle çalışır.

Kod optimize edilmemiştir ancak ana fikri vurgulamaktadır:

GÜNCELLEME

İşte kodun ilk optimizasyonu:

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>

Bunun için dom-to-image eklentisi kullanıyorum .


Bir akar yavaş çalışan, ancak bu şimdiye kadar sürekli çalışan ilk çözümdür. (Teknik merkezli  garip görünüyor uyarı ile.)
Brilliand

@Brilliand Ben cevabına yorum Âyaparken merkezlemesinin en uygun olmadığını göstermek için açıkça kullandım ;) Bunu gördükten sonra muhtemelen fikrini değiştirecek ve yazı tipinin çalışma şeklini kabul edecek
Temani Afif

Bu oldukça iyi görünüyor. Daha verimli hale getirebilirsem bunu kullanacağımı düşünüyorum. Şu anda biraz yavaş görünüyor.
Chron Bag

@ChronBag evet kod üzerinde çalışabilir ve optimize edebilirsiniz, bunun için yer var. Çok fazla zamanım olduğu için yapmadım ve gerçekten sorunun amacı değil. Ana fikre odaklanmak istedim. Muhtemelen bu arada daha sonra yapacak.
Temani Afif

@ChronBag bir optimizasyon ekledi, sanırım biraz daha hızlı.
Temani Afif

1

Belki daha iyi bir cevap var, ancak kulağa gelip gelmediğine bağlı olarak farklı stilleri manuel olarak uygulamak tek yol gibi geliyor:

  • Büyük harf
  • Kuyruklu küçük harf
  • Bir sap ile küçük harf
  • Hiçbiri ile küçük harf

Şimdi anladığım kadarıyla, bence kuyrukların ve sapların göreceli yüksekliklerinin yazı tipi tarafından tanımlandığını unutmayın. Buna programlı olarak erişmenin bir yolu olup olmadığından emin değilim - bu nedenle bu değerleri yazı tipiyle ayarlamanız gerekebilir.

Ayrıca, bu çözümün birden fazla dili desteklemek için işe yaramayacağını unutmayın - çünkü her bir karakterin onlarca farklı karakter setinde hangi kategoriye uyduğunu tanımlamanız gerekir.

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>


Böyle bir şeyden kaçınmayı umuyordum, ama bu tek çözüm olabilir. Başka bir şey gelmezse, muhtemelen bunu kullanacağım. Teşekkürler
Chron Bag

2
Harf herhangi bir unicode harf (herhangi bir alfabeden) olabiliyorsa, bu işlem kullanılamaz hale gelir.
Brilliand

Sen unutmak ÂËveâë
Temani Afif

Ah evet, iyi bir nokta @ Brilliand Kullanıcılarım ekran adları için herhangi bir unicode metin kullanabilecektir, bu yüzden bu çözüm daha da kırılgandır.
Chron Bag

0

Bu zor bir durum!

Söyleyebileceğim kadarıyla, bu doğal olarak ölçeklenir (yani yapmak en zor olacaktır %, vwya da vhyerine değerlerini pxveya em). Bu görünümün mobil veya tablette güzel görünmesi gerekiyorsa, lütfen çözümümü @mediakesme noktalarıyla kullanmayı düşünün .

Eğer bu bir Çözümümün esasen algılar küçük elemanı kuyruklu ve kuyruk telafi etmek yüksekliğini dengelemek için bir sınıf ekler.

Testlerimde, büyük harfler veya kuyruksuz küçük harfler için herhangi bir ek işleyiciye ihtiyaç duyulmadı . Eğer yanılıyorsam, beni düzeltmekten çekinmeyin.

Bu karışıklığı değiştirmek ve bu çözümü değiştirmek / test etmek istiyorsanız bir JSFiddle var .

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>

Düşüncelerinizi bana bildirin ve bir şey kaçırırsam. Geçmişte kendim de benzer sorunlarım olduğu için bunun için nihai bir çözüm elde etmek harika olurdu!


Bu dwjohnsson'ın çözümüne benziyor ve onunla aynı tuzaklara maruz kalıyor. Bununla birlikte, takdir edilir ve daha ideal bir şey gelmezse, bu çizgiler boyunca bir şeyle devam edebilirim.
Chron Bag

Sanırım son çare olarak, piksel sayım yolundan aşağıya inebilirsiniz - burada görüldüğü gibi , piksel cinsinden gerçek yüksekliğini tespit edip uygun ofseti uygularsınız.
EGC

1
Evet bu fikre OP'nin yorumlarında değindim. Belki de gitmenin yolu budur.
Chron Bag

Fikrinizi tekrar not etmek için üzgünüm .. çok fazla yorum, belli ki kaçırdı!
EGC

-1

Büyük harfleri büyük harflerden daha fazla çevirebilmeniz için muhtemelen bunun için bir yardımcı sınıfa ihtiyacınız olacaktır. Basit bir komut dosyası bu yardımcı sınıfları otomatik olarak kolayca yerleştirebilir.

Umarım bu sizin için sorunu çözer :)

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


senin yortada değil. Biraz daha çek!
Roko C. Buljan

Ayrıca mektupların ne olacağını önceden bilmiyorum.
Chron Bag

Bunu anlıyorum, ancak mektubun büyük veya küçük olup olmadığını kontrol eden ve HTML'ye bir yardımcı sınıfı koyan bunu kolayca düzelten bir komut dosyası :)
Ragna Roaldset

@RagnaRoaldset Bence büyük ya da küçük harf anlamına gelmiyor. Küçük harfli ama farklı bir karakter şekli demekti. Karşılaştırın ove yelde edersiniz. Kuyruklu karakterler sorunu ilk etapta yaratır (postada belirtilir).
Anna

1
Her zaman kuyruklu tüm harfler için bir dizi oluşturabilir ve div uygulamasındaki harfin sınıfı uygulamadan önce eşleşip eşleşmediğini kontrol etmek için döngü yapabilirsiniz :) Ama anladım, sadece bir çözümle gelmeye çalıştım :) umarım birisi gelir it :)
Ragna Roaldset
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.