Подтвердить что ты не робот

CSS: смещение текста без изменения размера контейнера

У меня есть меню горизонтальной навигации, которое в основном просто <ul> с элементами, расположенными бок о бок. Я не определяю ширину, но просто использую padding, потому что я хотел бы, чтобы ширина была определена по ширине элемента меню. Я выделен жирным шрифтом в текущем выбранном элементе.

Проблема заключается в том, что при смещении слово становится немного шире, что приводит к тому, что остальные элементы слегка сдвигаются влево или вправо. Есть ли умный способ предотвратить это? Что-то вроде строк, указывающих на прописку, чтобы игнорировать лишнюю ширину, вызванную смелостью? Моя первая мысль заключалась в том, чтобы просто вычесть несколько пикселей из дополнения активного элемента, но это количество варьируется.

Если возможно, я бы хотел, чтобы избежать установки статической ширины для каждой записи, а затем центрирования в отличие от используемого в настоящее время дополнения, чтобы сделать будущие изменения в простых элементах.

4b9b3361

Ответ 1

У меня была та же проблема, но я получил похожий эффект с небольшим компромиссом, вместо этого я использовал текстовую тень.

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>

Ответ 2

Лучшее рабочее решение, использующее:: 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/

Кредит: fooobar.com/questions/48166/...

Ответ 3

Наиболее переносимым и визуально приятным решением будет использование text-shadow. Это пересматривает и показывает примеры ответа Торгейра с использованием Alexxali и моих собственных настроек:

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

Это помещает крошечные "тени" в черный цвет (используйте название/код цвета шрифта вместо black если необходимо) с обеих сторон каждой буквы, используя единицы измерения, которые будут правильно масштабироваться при рендеринге шрифта.

warningПредупреждение: значения px поддерживают десятичные значения, но они не будут выглядеть так здорово при изменении размера шрифта (например, пользователь масштабирует представление с помощью Ctrl + +). Вместо этого используйте относительные значения.

В этом ответе используются доли ex единиц, поскольку они масштабируются шрифтом.
В большинстве браузеров по умолчанию * ожидайте 1ex8px и, следовательно, 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>

Ответ 4

Я обнаружил, что большинство шрифтов имеют одинаковый размер, когда вы настраиваете расстояние между буквами на 1px.

a {
   letter-spacing: 1px;
}

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

Пока это изменяет обычный шрифт, так что каждая буква имеет дополнительное расстояние между пикселями. Для меню названия настолько коротки, что это не представляет проблемы.

Ответ 5

К сожалению, единственный способ избежать изменения ширины, когда текст выделен полужирным шрифтом, - это определить ширину элемента списка, однако, как вы заявляли, что это вручную, занимает много времени и не масштабируется.

Единственное, что я могу придумать, это использовать некоторый javascript, который вычисляет ширину вкладки до того, как она выделена жирным шрифтом, а затем применяет ширину в то же время, когда требуется жирный шрифт (либо при наведении, либо при нажатии).

Ответ 6

Используйте JavaScript для установки фиксированной ширины li на основе нерасширенного содержимого, затем жирным шрифтом, добавив стиль в тег <a> (или добавьте диапазон, если <li> не имеет дочерних элементов).

Ответ 7

Для более актуального ответа вы можете использовать -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 (Opera обычно является хорошим барометром), хотя я не тестировал его в Safari. Это не работает в IE11 или ниже.

Также обратите внимание, что он использует префикс -webkit, поэтому он не является стандартным, и поддержка может быть прекращена в будущем, поэтому не стоит полагаться на то, что это жирный шрифт, это действительно важно - лучше избегать этого метода, если только он не эстетичен.

Ответ 8

Это очень старый вопрос, но я возвращаюсь к нему, потому что у меня была эта проблема в разрабатываемом приложении, и я нашел здесь ответы на все вопросы.

(Пропустите этот абзац для TL; DR...) Я использую веб-шрифт Gotham из cloud.typography.com, и у меня есть кнопки, которые начинаются пустым (с белой рамкой/текстом и прозрачным фоном) и получают фон цвет при наведении. Я обнаружил, что некоторые цвета фона, которые я использовал, не очень хорошо контрастировали с белым текстом, поэтому я хотел изменить текст на черный для этих кнопок, но - будь то из-за визуального трюка или распространенных методов сглаживания - темный текст на светлом фоне всегда выглядит легче, чем белый текст на темном фоне. Я обнаружил, что увеличение веса с 400 до 500 для темного текста поддерживает почти такой же "визуальный" вес. Тем не менее, он увеличивал ширину кнопки на крошечную величину - долю пикселя - но этого было достаточно, чтобы кнопки слегка "дрожали", от чего я хотел избавиться.

Решение:

Очевидно, что это действительно сложная проблема, поэтому она требовала сложного решения. В конечном итоге я использовал отрицательный letter-spacing в тексте более жирного шрифта, как рекомендованный выше cgTag, но 1px был бы излишним, поэтому я просто рассчитал именно ту ширину, которая мне была бы нужна.

Изучив кнопку в Chrome devtools, я обнаружил, что ширина моей кнопки по умолчанию составляет 165,47 пикселя, а при наведении - 165,69 пикселя, то есть разница составляет 0,22 пикселя. Кнопка имела 9 символов, а значит:

0,22/9 = 0,024444 пикселей

Преобразовав это в единицы em, я мог бы сделать настройку размера шрифта независимой. Моя кнопка использовала размер шрифта 16 пикселей, поэтому:

0.024444/16 = 0.001527em

Так что для моего конкретного шрифта следующий CSS сохраняет одинаковые ширины кнопок при наведении:

.btn {
  font-weight: 400;
}

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

Немного протестировав и используя приведенную выше формулу, вы сможете найти точно правильное значение letter-spacing для вашей ситуации, и оно должно работать независимо от размера шрифта.

Единственное предостережение в том, что разные браузеры используют немного разные субпиксельные вычисления, поэтому, если вы стремитесь к этому уровню OCD с идеальной точностью до субпикселя, вам нужно будет повторить тестирование и установить разные значения для каждого браузера. Стили CSS, нацеленные на браузер, обычно не одобряются, и на это есть веская причина, но я думаю, что это единственный вариант использования, когда это единственный вариант, который имеет смысл.

Ответ 9

Интересный вопрос. Я полагаю, вы используете float, верно?

Ну, я не знаю никакой техники, которую вы можете использовать, чтобы избавиться от этого расширения шрифта, поэтому они будут стараться соответствовать минимальной требуемой ширине - и изменение толщины шрифта изменит это значение.

Единственное решение, которое я знаю, чтобы избежать этого изменения, - это тот, который, как вы сказали, вам не нужен: установка фиксированных размеров на li.

Ответ 10

Вы можете реализовать это как amazon.com меню "Shop by department". Он использует широкий div. Вы можете создать широкий div и скрыть его правую часть

Ответ 11

UPDATE: нужно использовать тег B для заголовка, потому что в IE11 псевдокласс i: после не отображался, когда у меня была видимость: hidden.

В моем случае я хочу выровнять (настраиваемый) входной флажок/радио с текстом ярлыка, где текст выделяется жирным шрифтом при проверке ввода.

Решение, представленное здесь, не работает для меня в Chrome. Вертикальное выравнивание ввода и метки перепуталось с: после класса 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>