CSS : 컨테이너 크기를 변경하지 않고 일부 텍스트를 굵게 표시


119

기본적으로 <ul>요소가 나란히 설정된 가로 탐색 메뉴가 있습니다. 너비를 정의하지 않고 단순히 패딩을 사용합니다. 너비가 메뉴 항목의 너비로 정의되기를 원하기 때문입니다. 현재 선택된 항목을 굵게 표시합니다.

문제는 굵게 표시하면 단어가 약간 더 넓어지고 나머지 요소가 왼쪽이나 오른쪽으로 약간 이동한다는 것입니다. 이런 일이 발생하지 않도록하는 현명한 방법이 있습니까? 굵은 글씨로 인한 추가 너비를 무시하도록 패딩에 지시하는 내용이 있습니까? 내 첫 번째 생각은 단순히 "활성"요소의 패딩에서 몇 픽셀을 빼는 것이었지만이 양은 다양합니다.

가능한 경우 각 항목에 정적 너비를 설정 한 다음 현재 가지고있는 패딩 솔루션과 반대로 중앙에 배치하는 것을 피하고 싶습니다. 나중에 항목을 간단하게 변경할 수 있습니다.


크기 변경이 문제가되는 이유는 무엇입니까? 어떻게 든 레이아웃이 엉망입니까?
Chaulky 2011

웹 프로그래밍 질문은 Stack Overflow에서 가장 잘 묻는 것 같습니다. 아마도 모드가 이것을 그곳으로 마이그레이션 할 것입니다.
Ciaran 2011

2
Chaulky : 버튼을 클릭해야 할 때보 다 레이아웃 측면에서 더 싫어하는 것이 거의 없기 때문에
Mala

doejo.com/blog/… 는 John과 Blowski가 jscript에 대해 말한 것과 정확히 일치하는 솔루션 중 하나입니다.
thebulfrog

답변:


152

나는 같은 문제가 있었지만 약간의 타협으로 비슷한 효과를 얻었고 대신 텍스트 그림자를 사용했습니다.

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

다음은 작동하는 예입니다.

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 예


51
이 솔루션을 좋아하지만 1px 0px 0px로 전환하는 것이 좋습니다. 좀 더 대담 해 보입니다.
M. Herold 2013 년

CSS 전용 솔루션이 필요했고 이것이 답입니다.
JCasso 2013 년

당신의 진짜 천재! 단순함은 그것을 끔찍하게 만듭니다!
lufi

1
추가 li:hover {text-shadow: 1px 0 0 black;}만하면 글자 사이의 간격이 너무 적은 텍스트가 생성됩니다. 이를 다시 개선하기 위해 우리는 또한 설정했습니다li {letter-spacing: 1px;}
Patrick Hammer

5
-0.5px 0 #fff, 0.5px 0 #fff텍스트 자체와 그림자 사이의 작은 간격을 볼 수 있었기 때문에를 사용했습니다 . 또한 텍스트가 굵게 표시되면 양쪽에 가중치가 추가됩니다.
atorscho

101

:: after를 사용한 최상의 작업 솔루션

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속성에 의해 제공되는 굵은 텍스트 너비의 보이지 않는 의사 요소를 추가 합니다.

그만큼 text-shadow 솔루션은 Mac에서 부 자연스럽게 보이며 Mac에서 텍스트 렌더링이 제공하는 모든 아름다움을 활용하지 않습니다 .. :)

http://jsfiddle.net/85LbG/

크레딧 : https://stackoverflow.com/a/20249560/5061744


11
이것은 가장 안정적이고 깨끗한 솔루션이며 요소에서 굵은 텍스트를위한 공간을 예약합니다. 제 경우에는 추가 의사 요소로 인해 높이가 변경되었습니다. 블록에 음수 margin-top를 추가하면 ::after문제가 해결되었습니다.
Vaclav Novotny

2
이 솔루션은 훌륭합니다! HTML을 변경하지 않도록 JS를 사용하여 요소의 텍스트를 포함하는 "data-content"속성을 추가했습니다.
mistykristie 18:57에

1
대박. 이것이 최선의 답이 될 것입니다. li와 다른 요소가 있으면 display : block을 사용해야 할 수도 있습니다. : after 부모 요소.
Blackbam

훌륭한 솔루션! :: before에서도 잘 작동합니다. 제 경우에는 하단에 추가 여백을 방지합니다.
Thomas Champion

이 솔루션에 감사드립니다. 처음에는 text-shadow를 사용했지만 십진수 값을 반올림하기 때문에 Safari에서는 작동하지 않습니다. 0.1px를 사용했기 때문에 이것은 0으로 반올림되었습니다. 귀하의 솔루션은 완벽하게 작동했습니다. 내가 표시하는 툴팁을 원하지 않았다 나는 단지 이름이 제목 속성을 대체
조나단 Cardoz을

32

가장 휴대 가능하고 시각적으로 만족스러운 솔루션은를 사용하는 것 text-shadow입니다. 이것은 Alexxali 와 내 자신의 조정을 사용하여 Thorgeir의 답변의 예를 수정하고 보여줍니다 .

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

이렇게 black하면 글꼴 렌더링과 함께 적절하게 크기가 조정되는 단위를 사용하여 각 문자의 양쪽 에 작은 "그림자"가 검은 색 ( 필요한 경우 대신 글꼴의 색상 이름 / 코드 사용)으로 표시됩니다.

경고 경고 : px 값은 십진수 값을 지원하지만 글꼴 크기가 변경 될 때 (예 : 사용자가 Ctrl++ . 대신 상대 값을 사용하십시오.

이 답변은 ex글꼴에 따라 크기가 조정되므로 단위의 분수를 사용합니다 .
~ 대부분의 브라우저 기본값 * 에서 1ex≈을 예상 8px하므로 0.025ex0.1px.

직접 확인 :

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>

렌더링 된 선 위로 마우스를 가져 가면 표준 텍스트와 어떻게 다른지 확인할 수 있습니다.

브라우저의 확대 / 축소 수준 변경 ( Ctrl+ +Ctrl+- )을 차이를 확인합니다.

비교를 위해 여기에 두 가지 다른 솔루션을 추가했습니다 : @cgTag의 글자 간격 트릭 ( 글꼴 너비 범위 추측과 관련이 있기 때문에 잘 작동하지 않음)과 @ workaholic_gangster911의 :: after drawing 트릭 ( 굵은 텍스트가 확장 될 수 있도록 어색한 추가 공간을 남깁니다) 인접한 텍스트 항목을 뉘우 치지 않고 (저는 굵은 텍스트 뒤에 속성을 넣어서 어떻게 움직이지 않는지 볼 수 있습니다).


미래에, 우리는 더 할 것이다 변수 글꼴 변경 같은 것들을 할 수있는 글꼴 등급을 통해를 font-variation-settings. 브라우저 지원 이 증가하고 있지만 (Chrome 63+, Firefox 62+) 여전히 표준 글꼴 이상이 필요하며이를 지원하는 기존 글꼴은 거의 없습니다.

가변 글꼴을 삽입하면 다음과 같이 CSS를 사용할 수 있습니다.

/* 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; }
}

Mozilla Variable Fonts Guide에 다양한 등급으로 플레이 할 수있는 슬라이더 가있는 라이브 데모 가 있습니다. 웹의 가변 글꼴에 대한 Google의 소개 에는 높은 등급과 등급 없음 사이의 전환을 보여주는 애니메이션 GIF가 있습니다.

등급 축을 토글하는 애니메이션 Amstelvar Alpha 글꼴 데모


1
너무 간단하고 아름답습니다.
Randy Hall

18

문자 간격을 1px로 조정하면 대부분의 글꼴이 같은 크기라는 것을 알았습니다.

a {
   letter-spacing: 1px;
}

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

이렇게하면 일반 글꼴이 변경되어 각 문자에 추가 픽셀 간격이 있습니다. 메뉴의 경우 제목이 너무 짧아서 문제가되지 않습니다.


3
이것이 가장 좋고 가장 과소 평가 된 솔루션이지만 0으로 시작하고 굵게 표시되면 음수 문자 간격으로 이동하도록 변경했습니다. 또한 각 글꼴 및 글꼴 크기에 대해 미세 조정해야합니다. 나는 또한 (2 솔루션)이 포함되도록 Thorgeir의 바이올린 @ 업데이트 jsfiddle.net/dJcPn/50/
robotik

최신 브라우저는 이제 하위 픽셀 정확도를 지원합니다. 따라서 0.98px또는 더 작은 분수를 사용하여 간격을 미세 조정할 수 있습니다 .
Reactgular

간격 알고리즘이 정확히 동일하지 않기 때문에 약간 이상해 보입니다 (일부 글자가 약간 춤추고 있음). 더 중요한 것은 글꼴 크기를 조정할 때 또는 1px같은 상대 값으로 변환하더라도 작동하지 않기 때문 입니다. 라이브 데모에 대한 내 대답 을 참조하십시오 . 0.025ex0.0125ex
Adam Katz 2017

@AdamKatz이 답변이 게시 된 이후로 글꼴 렌더링이 변경된 것으로 의심되며 사용중인 글꼴에 따라 많이 달라집니다.
Reactgular

5

최신 답변을 보려면 다음을 사용할 수 있습니다 -webkit-text-stroke-width.

.element {
  font-weight: normal;
}

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

이렇게하면 가상 요소 (화면 판독기의 장점)와 텍스트 그림자 (지저분 해 보이지만 여전히 약간의 '점프'효과를 생성 할 수 있음) 또는 고정 너비 설정 (비실용적 일 수 있음)을 피할 수 있습니다.

또한 요소를 1px보다 굵게 설정할 수 있습니다 (이론적으로 글꼴을 원하는대로 굵게 만들 수 있으며 굵게 표시되지 않은 글꼴의 굵은 버전을 만들기위한 조잡한 운동이 될 수도 있습니다. 사용자 정의 글꼴과 같은 변형 ( 편집 : 가변 글꼴은이 제안을 평가하지 않음). 일부 글꼴이 긁히고 들쭉날쭉하게 보이기 때문에 피해야합니다.)

나는 Edge, Firefox, Chrome 및 Opera (게시 시점) 와 Safari ( 편집 : @Lars Blumberg를 확인해 주셔서 감사 합니다)에서 확실히 작동합니다 . IE11 이하에서는 작동하지 않습니다.

또한 -webkit접두사를 사용 하므로 이는 표준이 아니며 향후 지원이 중단 될 수 있으므로 굵게 표시되는 것이 정말 중요합니다. 단순히 미적인 경우가 아니라면이 기술을 피하는 것이 가장 좋습니다.


1
Safari 13.0.5에서도 작동합니다. 지금까지 나를위한 가장 깨끗한 솔루션.
Lars Blumberg

4

안타깝게도 텍스트가 굵게 표시 될 때 너비가 변경되는 것을 방지하는 유일한 방법은 목록 항목의 너비를 정의하는 것입니다. 그러나 수동으로 이렇게하는 것은 시간이 많이 걸리고 확장 할 수 없습니다.

내가 생각할 수있는 유일한 것은 탭이 굵게 표시되기 전에 탭의 너비를 계산 한 다음 굵게 표시되는 동시에 너비를 적용하는 자바 스크립트를 사용하는 것뿐입니다 (마우스 오버하거나 클릭 할 때).


음, JS가 아닌 사용자에게는 적어도 합리적으로 보이기를 원하지만 (즉, 굵게) 이것을 실험 해 볼 것입니다. 굵게 표시하고 JS를 사용하여 굵게 표시하고 너비를 계산 한 다음 다시 굵게 표시 할 수 있습니까? 아니면 그냥 어리석은가요?
Mala

예, 비 자바 스크립트 사용자를 수용하는 가장 좋은 방법 인 것 같습니다.
ajcw 2011

2

자바 스크립트를 사용하여 굵게 표시 되지 않은 콘텐츠를 기반으로 li의 고정 너비를 설정 한 다음 <a>태그에 스타일을 적용하여 콘텐츠를 굵게 표시합니다 (또는에 <li>자식이없는 경우 범위를 추가 ).


죄송합니다-반복해서 죄송합니다 : $
Dan Blows

어쨌든 답변 주셔서 감사합니다 :)
Mala

@Mala 해결책을 찾았습니까? 재미있게도 비슷한 문제가 있습니다.
Dan Blows 2011

1

이것은 매우 오래된 질문이지만 제가 개발중인 앱에이 문제가 있었고 여기에서 원하는 모든 답변을 찾았 기 때문에 다시 검토하고 있습니다.

(TL; DR에 대해서는이 단락을 건너 뛰십시오 ...)cloud.typography.com의 Gotham 웹 폰트를 사용하고 있으며 비어있는 버튼 (흰색 테두리 / 텍스트 및 투명한 배경)으로 시작하고 마우스 오버시 배경색을 얻는 버튼이 있습니다. 사용하던 배경색 중 일부가 흰색 텍스트와 잘 대조되지 않았기 때문에 해당 버튼의 텍스트를 검은 색으로 변경하고 싶었지만 시각적 트릭이나 일반적인 앤티 앨리어싱 방법으로 인해 어두운 밝은 배경의 텍스트는 항상 어두운 배경의 흰색 텍스트보다 더 가벼운 것처럼 보입니다. 어두운 텍스트의 가중치를 400에서 500으로 늘리면 거의 동일한 "시각적"가중치가 유지된다는 것을 알았습니다. 그러나 버튼 너비를 픽셀의 일부로 조금씩 늘 렸지만 버튼이 약간 "떨리는"것처럼 보이게하는 것으로 충분했습니다. 제가 제거하고 싶었습니다.

해결책:

분명히 이것은 매우 까다로운 문제이므로 까다로운 솔루션이 필요했습니다. 궁극적 letter-spacing으로 위에서 권장 한 cgTag와 같이 굵은 텍스트에 네거티브 를 사용 했지만 1px는 너무 과도했을 것이므로 정확히 필요한 너비를 계산했습니다.

Chrome devtools의 버튼을 검사 한 결과 내 버튼의 기본 너비는 165.47px이고 호버시 165.69px로 0.22px의 차이를 나타 냈습니다. 버튼에는 9 개의 문자가 포함되어 있습니다.

0.22 / 9 = 0.024444px

이를 em 단위로 변환하면 조정 글꼴 크기를 알 수 없습니다. 내 버튼은 16px의 글꼴 크기를 사용했습니다.

0.024444 / 16 = 0.001527em

따라서 내 특정 글꼴의 경우 다음 CSS는 버튼 을 마우스 오버시 정확히 동일한 너비로 유지합니다 .

.btn {
  font-weight: 400;
}

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

약간의 테스트와 위의 공식을 사용하면 letter-spacing상황에 맞는 정확한 값을 찾을 수 있으며 글꼴 크기에 관계없이 작동합니다.

한 가지주의 할 점은 브라우저마다 약간 다른 하위 픽셀 계산을 사용하므로이 OCD 수준의 하위 픽셀 완벽 정밀도를 목표로하는 경우 테스트를 반복하고 각 브라우저에 대해 다른 값을 설정해야합니다. 브라우저를 대상으로하는 CSS 스타일은 일반적으로별로 눈살을 찌푸 리지만 타당한 이유가있는 유일한 사용 사례라고 생각합니다.


0

흥미로운 질문입니다. 나는 당신이 float를 사용하고 있다고 생각합니다.

글쎄, 나는이 글꼴 확대를 제거하는 데 사용할 수있는 기술을 알지 못하므로 필요한 최소 너비에 맞추려고 노력할 것이며 글꼴 두께를 변경하면이 값이 변경됩니다.

이 변경을 피하기 위해 내가 아는 유일한 해결책은 당신이 원하지 않는다고 말한 것입니다 : 고정 크기를 li로 설정하십시오.


0

amazon.com "부서별 쇼핑"호버 메뉴처럼이를 구현할 수 있습니다. 넓은 div를 사용합니다. 넓은 div를 만들고 오른쪽 부분을 숨길 수 있습니다.


0

업데이트 : IE11에서 내가 가시성을 가질 때 의사 클래스 i : after가 표시되지 않았기 때문에 제목에 B 태그를 사용해야했습니다. 숨김.

제 경우에는 입력이 선택되었을 때 텍스트가 굵게 표시되는 레이블 텍스트와 함께 (사용자 정의 디자인 된) 입력 확인란 / 라디오를 정렬하고 싶습니다.

여기에 제공된 솔루션은 Chrome에서 작동하지 않았습니다. 입력과 레이블의 수직 정렬이 : after psuedo 클래스로 엉망이되었고 -margins는 이것을 수정하지 않았습니다.

다음은 수직 정렬에 문제가없는 수정 사항입니다.

/* 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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.