CSS: kapsayıcısının boyutunu değiştirmeden bazı metni kalınlaştırma


119

Temelde <ul>yan yana yerleştirilmiş öğelerle birlikte yatay bir gezinme menüsüne sahibim . Genişliği tanımlamıyorum, sadece dolgu kullanıyorum, çünkü genişliklerin menü öğesinin genişliğine göre tanımlanmasını istiyorum. Şu anda seçili öğeyi kalınlaştırıyorum.

Buradaki sorun, kalınlamada kelimenin biraz daha geniş olması ve bu da öğelerin geri kalanının hafifçe sola veya sağa kaymasına neden olmasıdır. Bunun olmasını önlemenin akıllıca bir yolu var mı? Dolguya, kalınlığın neden olduğu ekstra genişliği göz ardı etmesini söyleyen bir şey var mı? İlk düşüncem, "etkin" öğenin dolgusundan basitçe birkaç piksel çıkarmaktı, ancak bu miktar değişir.

Mümkünse, girişlerde gelecekteki değişiklikleri basitleştirmek için, her girişte statik bir genişlik ayarlamaktan ve ardından şu anda sahip olduğum dolgu çözümünün aksine ortalamaktan kaçınmak istiyorum.


boyut değişikliği neden bir problemdir? Bir şekilde düzeni bozuyor mu?
Chaulky

Bence web programlama sorusu en iyi Stack Overflow'da sorulur. Belki bir mod bunu oraya taşır.
Ciaran

2
Chaulky: çünkü, düzen olarak, düğmelere tıklamaktan daha çok nefret ettiğim birkaç şey var
Mala

doejo.com/blog/… , John ve Blowski'nin jscript hakkında söylediklerini tam olarak yapan bulduğum bir çözüm.
thebulfrog

Yanıtlar:


152

Aynı sorunu yaşadım, ancak biraz uzlaşmayla benzer bir etki elde ettim, bunun yerine metin gölge kullandım.

li:hover {text-shadow:0px 0px 1px black;}

İşte çalışan bir örnek:

body {
  font-family: segoe ui;
}

ul li {
  display: inline-block;
  border-left: 1px solid silver;
  padding: 5px
}

.textshadow :hover {
  text-shadow: 0px 0px 1px black;
}

.textshadow-alt :hover {
  text-shadow: 1px 0px 0px black;
}

.bold :hover {
  font-weight: bold;
}
<ul class="textshadow">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 0px 0px 1px black;</code></li>
</ul>

<ul class="textshadow-alt">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>text-shadow: 1px 0px 0px black;</code></li>
</ul>

<ul class="bold">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li><code>font-weight: bold;</code></li>
</ul>

jsfiddle örneği


51
Bu çözümü seviyorum, ancak onu 1px 0px 0px'e çevirmenizi tavsiye etmeme rağmen. Biraz daha cesur görünüyor.
M. Herold

Yalnızca css içeren bir çözüme ihtiyacım vardı ve bu yanıt.
JCasso

sen gerçek bir dahisin! basitlik onu harika kılar!
lufi

1
Yalnızca ekleme li:hover {text-shadow: 1px 0 0 black;}, harfler arasında çok az boşluk olan metinle sonuçlandı. Bunu tekrar iyileştirmek için,li {letter-spacing: 1px;}
Patrick Hammer

5
Kullandım -0.5px 0 #fff, 0.5px 0 #fff, çünkü metnin kendisi ile gölge arasındaki küçük boşluğu görebiliyorduk. Ayrıca metin kalın olduğunda, her iki tarafa da ağırlık ekler.
atorscho

101

:: after kullanarak en iyi çalışma çözümü

HTML

<li title="EXAMPLE TEXT">
  EXAMPLE TEXT
</li>

CSS

li::after {
  display: block;
  content: attr(title);
  font-weight: bold;
  height: 1px;
  color: transparent;
  overflow: hidden;
  visibility: hidden;
}

titleÖznitelik kaynaklı, kalın metin genişliğine sahip görünmez bir sözde öğe ekler .

text-shadowÇözelti Mac üzerinde doğal olmayan görünüyor ve metin Mac teklifleri render tüm güzelliği kullanmaz .. :)

http://jsfiddle.net/85LbG/

Kredi: https://stackoverflow.com/a/20249560/5061744


11
Bu en güvenilir ve temiz çözümdür, basitçe öğede kalın metinler için yer ayırır. Benim durumumda, ek sözde eleman yükseklik değişikliğine neden oldu. Bloğa negatif eklemek margin-topbunu ::afterçözdü.
Vaclav Novotny

2
Bu çözüm harika! HTML'yi değiştirmekten kaçınabilmek için, öğenin metnini içeren bir "veri içeriği" özniteliği eklemek için JS kullandım.
mistykristie

1
Muhteşem. En iyi cevap bu olmalı. Li öğesinden farklı bir öğe varsa, display: block kullanmanız gerekebileceğini unutmayın; üzerinde: sonra üst öğeden.
Blackbam

Harika çözüm! Daha önce :: ile iyi çalışıyor, benim durumumda bu, altta ek marjı engelliyor.
Thomas Champion

Bu çözüm için teşekkür ederim. Başlangıçta metin gölge kullandım, ancak bu, ondalık değerleri yuvarlarken Safari'de çalışmıyor. 0.1px kullandığım için bu 0'a yuvarlanıyordu. Çözümünüz kusursuz çalıştı. Araç ipuçlarının görünmesini istemediğim için başlık özelliğini yalnızca adla değiştirdim
Jonathan Cardoz

32

En taşınabilir ve görsel olarak memnun edici çözüm kullanmak olacaktır text-shadow. Bu, Thorgeir'in Alexxali ve benim kendi ince ayarlarımı kullanarak cevabının örneklerini gözden geçiriyor ve gösteriyor :

  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }

Bu, blackyazı tipi oluşturma ile doğru şekilde ölçeklenecek birimler kullanarak her bir harfin her iki tarafına da küçük "gölgeleri" siyaha ( gerekirse yazı tipinizin renk adını / kodunu kullanın) koyar .

uyarı Uyarı: px değerler ondalık değerleri destekler, ancak yazı tipi boyutu değiştiğinde çok iyi görünmezler (örneğin, kullanıcı görünümü Ctrl+ ile ölçeklendirir +). Bunun yerine göreli değerler kullanın.

Bu cevap ex, yazı tipine göre ölçeklendikleri için birimlerin kesirlerini kullanır .
In ~ En tarayıcı varsayılan olarak * , bekliyoruz 1ex8pxnedenle ve 0.025ex0.1px.

Kendin için gör:

li             { color: #000; } /* set text color just in case */
.shadow0       { text-shadow: inherit; }
.shadow2       { text-shadow: -0.02ex 0 #000, 0.02ex 0 #000; }
.shadow4       { text-shadow: -0.04ex 0 #000, 0.04ex 0 #000; }
.shadow6       { text-shadow: -0.06ex 0 #000, 0.06ex 0 #000; }
.shadow8       { text-shadow: -0.08ex 0 #000, 0.08ex 0 #000; }
.bold          { font-weight: bold; }
.bolder        { font-weight: bolder; }
.after span        { display:inline-block; font-weight: bold; } /* workaholic… */
.after:hover span  { font-weight:normal; }
.after span::after { content: attr(title); font-weight: bold; display:block; 
                     height: 0; overflow: hidden; }
.ltrsp         { letter-spacing:0; font-weight:bold; } /* @cgTag */
li.ltrsp:hover { letter-spacing:0.0125ex; }
li:hover       { font-weight: normal!important; text-shadow: none!important; }
<li class="shadow0">MmmIii123 This line tests shadow0 (plain)</li>
<li class="shadow2">MmmIii123 This line tests shadow2 (0.02ex)</li>
<li class="shadow4">MmmIii123 This line tests shadow4 (0.04ex)</li>
<li class="shadow6">MmmIii123 This line tests shadow6 (0.06ex)</li>
<li class="shadow8">MmmIii123 This line tests shadow8 (0.08ex)</li>
<li class="after"><span title="MmmIii123 This line tests [title]"
                   >MmmIii123 This line tests [title]</span> (@workaholic…)</li>
<li class="ltrsp"  >MmmIii123 This line tests ltrsp (@cgTag)</li>
<li class="bold"   >MmmIii123 This line tests bold</li>
<li class="bolder" >MmmIii123 This line tests bolder</li>
<li class="shadow2 bold">MmmIii123 This line tests shadow2 (0.02ex) + bold</li>
<li class="shadow4 bold">MmmIii123 This line tests shadow4 (0.04ex) + bold</li>
<li class="shadow6 bold">MmmIii123 This line tests shadow6 (0.06ex) + bold</li>
<li class="shadow8 bold">MmmIii123 This line tests shadow8 (0.08ex) + bold</li>

Standart metinden ne kadar farklı olduklarını görmek için imleci oluşturulan satırların üzerine getirin.

Tarayıcınızın yakınlaştırma düzeyini değiştirin ( Ctrl+ +ve Ctrl+-Nasıl değiştiklerini görmek ) değiştirin.

Karşılaştırma için buraya iki çözüm daha ekledim: @ cgTag'in harf aralığı hilesi yazı tipi genişliği aralıklarını tahmin etmeyi gerektirdiği için pek iyi çalışmayan ve @ workaholic_gangster911'in :: çizim hilesi , kalın metnin genişleyebilmesi için garip fazladan boşluk bırakıyor komşu metin öğelerini dürtmeden (nasıl hareket etmediğini görebilmeniz için atfı kalın metinden sonra koyarım).


Gelecekte, yazı tipi derecesini değiştirmek gibi şeyler yapabilen daha değişken yazı tiplerine sahip olacağız aracılığıyla font-variation-settings. Tarayıcı desteği artıyor (Chrome 63+, Firefox 62+), ancak bu hala standart yazı tiplerinden fazlasını gerektiriyor ve birkaç mevcut yazı tipi bunu destekliyor.

Değişken bir yazı tipi yerleştirirseniz, CSS'yi şu şekilde kullanabilirsiniz:

/* Grade: Increase the typeface's relative weight/density */
@supports (font-variation-settings: 'GRAD' 150) {
  li:hover { font-variation-settings: 'GRAD' 150; }
}
/* Failover for older browsers: tiny shadows at right & left of the text
 * (replace both instances of "black" with the font color) */
@supports not (font-variation-settings: 'GRAD' 150) {
  li:hover { text-shadow: -0.06ex 0 black, 0.06ex 0 black; }
}

Bir yoktur canlı tanıtım Mozilla Değişken Yazı Kılavuzu üzerinde çeşitli dereceleri ile oynamak için bir kaydırıcı ile. Google'ın web'deki değişken yazı tiplerine Giriş, yüksek dereceli ve derecesiz arasında geçişi gösteren animasyonlu bir GIF içerir:

derece ekseni geçişli animasyonlu Amstelvar Alpha yazı tipi demosu


1
Çok basit, çok güzel.
Randy Hall

18

Harf aralığını 1 piksel ayarladığınızda çoğu yazı tipinin aynı boyutta olduğunu buldum.

a {
   letter-spacing: 1px;
}

a:hover {
   font-weight: bold;
   letter-spacing: 0px;
}

Bu, normal yazı tipini değiştirirken, her harfin fazladan bir piksel aralığı vardır. Menüler için başlıklar o kadar kısadır ki sorun teşkil etmez.


3
Bu en iyi ve en az değer verilen çözümdür, ancak onu 0 ile başlayacak ve kalın olduğunda negatif harf aralığına gidecek şekilde değiştirdim. ayrıca her yazı tipi ve yazı tipi boyutu için ince ayar yapmanız gerekir. Ayrıca @ Thorgeir'in kemanını da bunu (2. çözüm olarak) içerecek şekilde güncelledim jsfiddle.net/dJcPn/50/
robotik

Modern tarayıcılar artık alt piksel doğruluğunu destekliyor. Böylece, 0.98pxkesirleri kullanarak veya daha küçük aralıklarla ince ayar yapabilirsiniz .
Reactgular

Aralık algoritması tam olarak aynı olmadığından (bazı harfler biraz dans eder) ve daha da önemlisi, yazı tipleri ölçeklendiğinde, veya 1pxgibi göreli değerlere dönüştürseniz bile, bu biraz tuhaf görünüyor . Canlı bir gösteri için cevabımı görün . 0.025ex0.0125ex
Adam Katz

@AdamKatz Bu cevabın gönderilmesinden bu yana yazı tipi oluşturmanın değiştiğinden şüpheleniyorum ve bu, kullandığınız yazı tipine çok bağlı.
Reactgular

5

Daha güncel bir cevap için şunları kullanabilirsiniz -webkit-text-stroke-width:

.element {
  font-weight: normal;
}

.element:hover {
  -webkit-text-stroke-width: 1px;
  -webkit-text-stroke-color: black;
}

Bu, herhangi bir sözde öğeleri (ekran okuyucular için bir artıdır) ve metin gölgelerini (dağınık görünen ve yine de hafif bir 'atlama' efekti oluşturabilen) veya herhangi bir sabit genişliğin ayarlanmasını (pratik olmayabilir) önler.

Ayrıca, bir öğeyi 1 pikselden daha kalın olacak şekilde ayarlamanıza da olanak tanır (teorik olarak, bir yazı tipini istediğiniz kadar kalın yapabilirsiniz ve ayrıca kalın olmayan bir yazı tipinin cesur bir sürümünü oluşturmak için kalitesiz bir çalışma olabilir. varyant, özel yazı tipleri gibi ( düzenleme: değişken yazı tipleri bu öneriyi amorti eder ). Muhtemelen bazı yazı tiplerinin cızırtılı ve pürüzlü görünmesine neden olacağından bundan kaçınılmalıdır)

Ben bu kesinlikle Edge, Firefox, Chrome ve Opera'da (yayınlama sırasında) ve Safari'de ( düzenleme: @Lars Blumberg bunu onayladığınız için teşekkürler ). IE11 veya altında çalışmaz.

Ayrıca, -webkitöneki kullandığını unutmayın, bu yüzden bu standart değildir ve gelecekte destek düşebilir, bu nedenle buna güvenmeyin cesur gerçekten önemlidir - yalnızca estetik olmadığı sürece bu teknikten kaçınmak en iyisidir.


1
Safari 13.0.5'te de çalışır. Şimdiye kadar benim için en temiz çözüm.
Lars Blumberg

4

Ne yazık ki, metin kalın olduğunda genişliğin değişmesini önlemenin tek yolu liste öğesinin genişliğini tanımlamaktır, ancak belirttiğiniz gibi bunu manuel olarak yapmak zaman alıcıdır ve ölçeklenebilir değildir.

Aklıma gelen tek şey, kalın olmadan önce sekmenin genişliğini hesaplayan ve ardından kalınlığın gerekli olduğu anda (ya üzerine geldiğinizde ya da tıklattığınızda) genişliği uygulayan bir javascript kullanmak.


hm, JS kullanıcısı olmayanlar için en azından mantıklı (yani kalın) görünmesini istesem de, bunu deneyeceğim. Belki kalın harflerle gönderebilirim, JS kullanarak kalınlaştırabilirim, genişliği hesaplayabilir ve sonra tekrar kalınlaştırabilirim? Yoksa bu sadece aptalca mı?
Mala

Evet, bu, javascript kullanmayan kullanıcıları barındırmanın en iyi yolu gibi görünüyor.
ajcw

2

Kalınlaştırılmamış içeriğe göre sabit bir li genişliği ayarlamak için JavaScript kullanın, ardından <a>etikete bir stil uygulayarak içeriği kalınlaştırın (veya alt öğe yoksa bir aralık ekleyin <li>).


Oops - tekrarladığım için özür dilerim: $
Dan Blows

Cevabınız için yine de teşekkürler :)
Mala

@Mala Bir çözüm buldunuz mu? Yeterince tuhaf bir şekilde, benzer bir sorunum var.
Dan Darbe

1

Bu çok eski bir soru, ama tekrar gözden geçiriyorum çünkü geliştirdiğim bir uygulamada bu problemi yaşadım ve tüm cevapları burada isteyerek buldum.

(TL için bu paragrafı atlayın; DR ...)Cloud.typography.com'dan Gotham web yazı tipini kullanıyorum ve içi boş (beyaz bir kenarlık / metin ve şeffaf bir arka plan ile) başlayan ve üzerine gelindiğinde bir arka plan rengi elde eden düğmelerim var. Kullandığım arka plan renklerinden bazılarının beyaz metinle iyi bir kontrast oluşturmadığını fark ettim, bu yüzden bu düğmeler için metni siyaha çevirmek istedim, ancak - ister görsel bir numara ister yaygın kenar yumuşatma yöntemleri nedeniyle - koyu açık renkli arka plan üzerindeki metin her zaman koyu arka plan üzerindeki beyaz metinden daha hafif görünür. Koyu metin için ağırlığı 400'den 500'e çıkarmanın neredeyse tamamen aynı "görsel" ağırlığı koruduğunu buldum. Bununla birlikte, düğme genişliğini küçücük bir miktar artırıyordu - bir pikselin bir kısmı - ama bu, düğmelerin biraz "titriyor" gibi görünmesini sağlamak için yeterliydi ki bundan kurtulmak istedim.

Çözüm:

Açıkçası, bu gerçekten titiz bir problem, bu yüzden titiz bir çözüm gerektiriyordu. Sonunda letter-spacingcgTag'in yukarıda önerdiği gibi daha kalın metinde bir negatif kullandım , ancak 1px çok fazla olurdu, bu yüzden tam olarak ihtiyacım olan genişliği hesapladım.

Chrome geliştirme araçlarındaki düğmeyi inceleyerek, düğmemin varsayılan genişliğinin 165.47px ve üzerine gelindiğinde 165.69px olduğunu buldum, bu fark 0.22px. Düğmede 9 karakter vardı, bu nedenle:

0,22 / 9 = 0,024444 piksel

Bunu em birimlerine dönüştürerek yazı tipi boyutunu agnostik yapabilirim. Düğmem 16px yazı tipi boyutu kullanıyordu, bu nedenle:

0,024444 / 16 = 0,001527em

Dolayısıyla, benim özel yazı tipim için, aşağıdaki CSS, düğmeleri fareyle üzerine gelindiğinde tam olarak aynı genişlikte tutar :

.btn {
  font-weight: 400;
}

.btn:hover {
  font-weight: 500;
  letter-spacing: -0.001527em;
}

Biraz test ederek ve yukarıdaki formülü kullanarak, letter-spacingdurumunuz için tam olarak doğru değeri bulabilirsiniz ve yazı tipi boyutundan bağımsız olarak çalışmalıdır.

Bir uyarı, farklı tarayıcıların biraz farklı alt piksel hesaplamaları kullanmasıdır; bu nedenle, bu OKB düzeyindeki piksel altı hassaslık düzeyini hedefliyorsanız, testi tekrarlamanız ve her tarayıcı için farklı bir değer ayarlamanız gerekir. Tarayıcı hedefli CSS stilleri genellikle iyi bir nedenden ötürü hoş karşılanmaz , ancak bunun mantıklı olan tek seçenek olduğu bir kullanım durumu olduğunu düşünüyorum.


0

İlginç soru. Sanırım float kullanıyorsunuz, değil mi?

Eh, bu yazı tipi büyütme işleminden kurtulmak için kullanabileceğiniz herhangi bir teknik bilmiyorum, bu nedenle gerekli minimum genişliğe sığmaya çalışacaklar - ve değişen yazı tipi kalınlığı bu değeri değiştirecektir.

Bu değişimden kaçınmak için bildiğim benzersiz çözüm, istemediğinizi söylediğiniz çözüm: sabit boyutları li'lere ayarlamak.


0

Bunu amazon.com "Departmana göre alışveriş" vurgulu menüsü gibi uygulayabilirsiniz. Geniş div kullanır. Geniş div oluşturabilir ve sağ kısmını gizleyebilirsiniz


0

GÜNCELLEME: Başlık için B etiketini kullanmak zorunda kaldım çünkü IE11'de sözde sınıf i: after, görünürlük: gizli olduğunda gösterilmedi.

Benim durumumda, (özel tasarlanmış) bir giriş onay kutusunu / radyoyu, giriş işaretlendiğinde metnin kalın olacağı etiket metni ile hizalamak istiyorum.

Burada sağlanan çözüm Chrome'da benim için işe yaramadı. Girdi ve etiketin dikey hizalanması: after psuedo sınıfıyla karıştı ve -margins bunu düzeltmedi.

Dikey hizalamalarda sorun yaşamadığınız bir düzeltme burada.

/* checkbox and radiobutton */
label
{
    position: relative;
    display: inline-block;
    padding-left: 30px;
    line-height: 28px;
}

/* reserve space of bold text so that the container-size remains the same when the label text is set to bold when checked. */
label > input + b + i
{
    font-weight: bold;
    font-style: normal;
    visibility: hidden;
}

label > input:checked + b + i
{
    visibility: visible;
}

/* set title attribute of label > b */
label > input + b:after
{
    display: block;
    content: attr(title);
    font-weight: normal;
    position: absolute;
    left: 30px;
    top: -2px;
    visibility: visible;
}

label > input:checked + b:after
{
    display: none;
}

label > input[type="radio"],
label > input[type="checkbox"]
{
    position: absolute;
    visibility: hidden;
    left: 0px;
    margin: 0px;
    top: 50%;
    transform: translateY(-50%);
}

    label > input[type="radio"] + b,
    label > input[type="checkbox"]  + b
    {
        display: block;
        position: absolute;
        left: 0px;
        margin: 0px;
        top: 50%;
        transform: translateY(-50%);
        width: 24px;
        height: 24px;
        background-color: #00a1a6;
        border-radius: 3px;
    }

    label > input[type="radio"] + b
    {
        border-radius: 50%;
    }

    label > input:checked + b:before
    {
        display: inline-block;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(45deg);
        content: '';
        border-width: 0px 3px 3px 0px;
        border-style: solid;
        border-color: #fff;
        width: 4px;
        height: 8px;
        border-radius: 0px;
    }

    label > input[type="checkbox"]:checked + b:before
    {
        transform: translate(-50%, -60%) rotate(45deg);
    }

    label > input[type="radio"]:checked + b:before
    {
        border-width: 0px;
        border-radius: 50%;
        width: 8px;
        height: 8px;
    }
<label><input checked="checked" type="checkbox"/><b title="Male"></b><i>Male</i></label>
<label><input type="checkbox"/><b title="Female"></b><i>Female</i></label>

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.