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

Вертикальное выравнивание на основе x-height

При попытке центрировать содержимое в контейнере CSS-Tricks имеет отличное руководство. Однако, пытаясь вертикально сосредоточить текст, который немного меньше его контейнера, я думаю, что предпочтительным вариантом вертикально центрирующего текста может быть предпочтительнее. Вместо того, чтобы использовать всю высоту шрифта, я бы предпочел сосредоточить его на основе x-высоты шрифта (в основном высота строчной буквы x)

Visual explanation of x-height

И посмотрите на этот пример, где красный - на всей высоте, а зеленый - на основе x-height

Difference between vertically centering

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

.pseudo {
  white-space: nowrap;
}

.pseudo:before {
  content: '';
  display: inline-block;
  vertical-align: middle;
  height: 100px;
  width: 0;
}

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

См. Codepen для примера о том, почему я хочу сосредоточить его на основе x-height, и мое решение.

4b9b3361

Ответ 1

Разница между расположением текстового центра и центром маленьких букв равна (ascender height - x-height - descender height)/2 (в основном нам нужно как-то увеличить высоту спуска, чтобы сделать ее равной ascender height - x-height, чтобы переместить геометрический центр строки в позицию центра маленьких букв). Из этих трех неизвестных доступно только x-height для CSS (через блок ex). Другие метрики шрифтов не могут быть прочитаны и остаются своего рода "магическими числами", поэтому можно выбрать только определенное значение для каждого конкретного шрифта. Но с помощью этого "волшебного номера шрифта" вы можете центрировать любое количество строк, предоставив внутренний элемент display:inline-block и присвоив magic value его padding-bottom.

Кажется невозможным получить необходимое значение из метрик шрифта в чистом CSS. Такие значения vertical-align как text-top/text-bottom могут задавать положение восходящего или нисходящего, но только один из них, экзотические значения, такие как sub, кажутся совершенно произвольными, и я не нашел возможности "измерить" разница между двумя метриками шрифта для одного элемента.

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

.blue:after {
  content: ':'; /* must contain text to get the auto height of the line box */
  display: inline-block;
  vertical-align: middle;
  width: 0; /* making pseudo elenent invisible */
  overflow: hidden;
}

Отредактированный пример CodePen с результатом (я не скрывал псевдоэлементы для визуализации).

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

Надеюсь, это поможет:)

Ответ 3

Я думаю, что единственный способ получить желаемый результат - использовать Dinamyc CSS (DCSS).

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

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

Вот пример, вставленный из этой ссылки http://www.phpsnaps.com/snaps/view/get-text-height-width/ о том, как получить высоту текста в PHP:

define("F_SIZE", 8);
define("F_FONT", "arial.ttf");


function get_bbox($text){
    return imagettfbbox(F_SIZE, 0, F_FONT, $text);
}

function text_height ($text) {
    $box = get_bbox($text);
    $height = $box[3] - $box[5];
    return $height;
}

function text_width ($text) {
    $box = get_bbox($text);
    $width = $box[4] - $box[6];
    return $width;
}

И тогда вы бы эхо ваш (x) HTML с CSS так или иначе:

echo "<span style=\"YourStyleProperty=" . **Your line height / 2 + your text height / 2 (Hint: use the PHP or equivalent if other language)** . ";\"

Для получения дополнительной информации о функции imagettfbbox: http://php.net/manual/fr/function.imagettfbbox.php

Не стесняйтесь публиковать сообщения, если у вас возникли проблемы с окончанием кода, я буду рад помочь, если вы продемонстрируете некоторые усилия:).

Для получения дополнительной информации о DCSS и, возможно, более эффективных идеях/примерах, не стесняйтесь обращаться к Google DCSS.

Ответ 4

Используйте этот css

.outer {
    display: table;
    width: 200px;
    height: 200px;
    background-color:blue;
}
.inner {
    display: table-cell;
    vertical-align: middle;
    /*You can align center if you want as well*/
    /*text-align:center;*/
}
.box {
    position: relative;
    display: inline-block;
    background: orange;
    color: black;
    font-size: 60px;
    background-color: yellow;
}

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

<div class="outer">
    <div class="inner">
        <div class="box">
            Texty</br>
            Texty
        </div>
    </div>
</div>

здесь codepen

Ответ 5

Вероятно, вам нужен один из этих плагинов jQuery:

  • FlowType: типичная веб-типография: размер шрифта и высота строки на основе ширины элемента
  • Squishy: плагин для подгонки текста заголовка к контейнеру
  • Отзывчивый текст: размер шрифта зависит от его ширины контейнера
  • TypeButter: Позволяет вам установить оптический кернинг для любого шрифта на вашем веб-сайте.
  • FitText: FitText делает шрифты гибкими
  • SlabText: плагин jQuery для создания больших, смелых и отзывчивых заголовков
  • Auto Line-Height: плагин jQuery для гибких макетов

Ответ 6

Илья Стрельцин ответ (принятый) поразителен. Именно то, что мне нравится в CSS - если вы хорошо знаете механику, вы можете выполнить что угодно.

Я обобщил принятый ответ на повторно используемый класс, протестированный в Chrome, Firefox и Edge. Я также исправил проблемы с тем, как он сидит в потоке документа (контейнер будет нести дополнительную ширину от элементов ::after и будет казаться ниже, чем элементы sibling). Вы можете легко использовать класс следующим образом:

<any class="x-height">
  <span class="x-height">
    Centered text
  </span>
</any>

И ниже находится источник Sass (Также проверьте его на Codepen):

%x-height {
  content: 'x';
  display: inline-block;
  vertical-align: middle;
  width: 0;
}

.x-height {
  vertical-align: bottom;

  &::after {
    @extend %x-height;

    content: '';
    height: 100%;
  }

  > .x-height {
    display: inline-block;
    vertical-align: baseline;
    margin-left: -1ch;
    margin-right: calc(-1ch / 2);
    white-space: nowrap;

    @at-root {
      @-moz-document url-prefix() {
        & {
          margin-left: auto;
          margin-right: auto;

          &::before { display: none; }
        }   
      }
    }

    &::before, &::after {
      @extend %x-height;
      visibility: hidden;
    }

    &::after {
      width: 1ch;
      margin: 0 -1ch;
    }
  }
}