Есть ли в CSS какой-либо способ выровнять элемент по концу последнего линейного блока родственного элемента?

#html #css

#HTML #css

Вопрос:

Есть ли какой-либо способ добиться макета, показанного в этом макете?

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

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

Вещи, которые я пробовал

Плавающий дополнительный текст.

Проблемы с этим подходом:

  • Это float, поэтому у него есть все крайние случаи и ошибки, которые есть у поплавков, и следующий элемент должен иметь дело с его очисткой, а поля действуют неожиданным образом.
  • Если дополнительный текст имеет другой размер, его трудно выровнять по той же базовой линии, что и основной текст, поскольку vertical-align он не работает с плавающими элементами. Их можно выровнять, если известны все размеры, но в большинстве случаев для этого потребуются дополнительные элементы-оболочки.
  • Чтобы использовать ту же строку, что и основной текст, дополнительный текст должен быть первым (для меня это неприемлемо) или основной текст должен быть плавающим, а не дополнительным. И последний случай работает только тогда, когда основной текст и дополнительный текст умещаются на одной строке, в противном случае дополнительный будет находиться ниже конечного линейного блока основного текста.

Вот он с дополнительным текстом, расположенным справа, в обоих порядках:

 article {
  clear: both;
}

header p {
  float: right;
} 
 <article>
  <header>
    <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
    <p>Supplementary</p>
  </header>
</article>

<article>
  <header>
    <p>Supplementary</p>
    <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
  </header>
</article> 

Flexbox

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

  • Если функция flex wrap не включена, дополнительный текст будет выравниваться только по первой базовой линии основного текста, а горизонтальная область, доступная для всех строк основного текста, уменьшается на то, сколько места занимает дополнительный текст.
  • Если включена функция flex wrap и основной текст переносится на вторую строку или иным образом не оставляет достаточно места для дополнительного текста, ширина элемента flex основного текста равна полной ширине гибкого блока или близка к ней, и поэтому дополнительный текст всегда будет находиться на новой гибкой строке, даже если для него доступно визуальное пространство в последнем линейном блоке основного текста.
 header {
  display: flex;
  align-items: baseline;
}

header p {
  margin-left: auto;
} 
 <header>
  <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
  <p>Supplementary</p>
</header>

<header style="flex-wrap: wrap">
  <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
  <p>Supplementary</p>
</header> 

Абсолютное позиционирование

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

Комментарии:

1. чтобы легко очистить float, просто добавьте overflow:auto в заголовок, это сделает элемент самоочищающимся, и не нужно беспокоиться о следующем элементе, очищающем его

Ответ №1:

Это, безусловно, интересный вопрос. К сожалению, на самом деле это кажется основным inline floated способом использования элементов и, какими бы неприятными они ни были. Конечно, немного сложнее понять, как они будут взаимодействовать в среде «реального мира», но если бы вы использовали исправление « :after как таблица», сделали h2 его встроенным, плавающим p и удалили высоту строки, он должен находиться в нижней части типографский x-высота h2 .

Вот краткая демонстрация:

 article:after {
  content: "";
  display: table;
  clear: both;
}
header h2 {
  display: inline;
}
header p {
  float: right;
  line-height: 0;
}

/* Just for example layout */
body{width:100vw;overflow-x:hidden;min-height:100vh;display:flex;align-items:center;justify-content:center}div{max-width:50%}header p{position:relative}header p:after{content:"";position:absolute;width:calc(50vw - 40px);height:1px;background:red;top:6px;right:0}article{padding:20px;border:1px solid #ccc} 
 <div>
  <article>
    <header>
      <h2>Lorem ipsum</h2>
      <p>Supplementary</p>
    </header>
  </article>
  <article>
    <header>
      <h2>Lorem ipsum dolor sit amet, adipi…</h2>
      <p>Supplementary</p>
    </header>
  </article>
  <article>
    <header>
      <h2>Lorem ipsum dolor sit amet, adipiscing Lorem ipsum dolor sit amet, adipiscing Lorem ipsum dolor sit amet, adipiscing Lorem ipsum.</h2>
      <p>Supplementary</p>
    </header>
  </article>
</div> 


Интересное замечание, как отметил @Temani Afif, вы можете заменить на article:after { content: ""; display: table; clear: both; } с header { overflow: auto; } , чтобы сделать его самоочищающимся. Небольшая хитрость, позволяющая предотвратить засорение вашего CSS четкими исправлениями

Комментарии:

1. О, это показывает, что в display: contents ответе used in nullqube не было необходимости; это улучшение. Расширенный пример здесь: codepen.io/tremby/pen/mdrXQYO — как вы увидите, я проделал много акробатических трюков, чтобы убедиться, что различия в высоте и размере линий учитываются во всех случаях…

2. Расширенный пример в моем предыдущем комментарии также обрабатывает несколько дополнительных строк (вместо установки высоты строки в 0, как в вашем примере). Я думаю, это решает проблему почти полностью, просто жаль, что размеры шрифта должны быть известны, что для выравнивания базовых линий требуется так много неприятностей calc , что задействовано магическое число, и что если дополнительный элемент один в строке, он занимает всю высоту строкиосновной текст.

3. Очистка etc — широко известная проблема, и ее не нужно указывать в ответе. Ничего, если я отредактирую ваш ответ, включив в него свой расширенный пример?

4. Я также должен отметить, что в вашем (гораздо более чистом и простом!) коде базовые линии выравниваются только по счастливой случайности — если размер шрифта основного или дополнительного текста изменен, они больше не будут выравниваться.

Ответ №2:

 h2 {
    display: contents;
}

p {
    float: right;
    transform: translateY(-50%);
}

article {
    clear: both;
}

article:after {
    content: "";
    display:block;
    width: 100%;
    height: 1px;
    background: red;
} 
 <article>
  <header>
    <h2>Lorem ipsum dolor sit amet, adipiscing blah blahh blahhhh, and long looong looooooong text content</h2>
    <p>Supplementary</p>
  </header>
</article>
<br>
<article>
  <header>
    <p>Supplementary</p>
    <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
  </header>
</article> 

а затем без display: contents и появившийся дополнительный пробел можно решить, установив line-height значение h2 (например: line-height:1em; )

 h2 {
    display: inline;
    /*line-height: 1em;*/
}

p {
    float: right;
    transform: translateY(-50%);
}

article {
    clear: both;
}

article:after {
    content: "";
    display:block;
    width: 100%;
    height: 1px;
    background: red;
} 
 <article>
  <header>
    <h2>Lorem ipsum dolor sit amet, adipiscing blah blahh blahhhh, and long looong looooooong text content</h2>
    <p>Supplementary</p>
  </header>
</article>
<br>
<article>
  <header>
    <p>Supplementary</p>
    <h2>Lorem ipsum dolor sit amet, adipiscing</h2>
  </header>
</article> 

Комментарии:

1. Интересно. Я взял это и запустил с ним; смотрите здесь: codepen.io/tremby/pen/NWRyEMv — основная проблема заключается в том, что display: contents это поддерживается не везде, и в браузерах на основе Chromium есть текущая ошибка, из-за которой она удаляется из дерева доступности (ссылка в примечаниях Codepen).

2. ооо, вы можете получить тот же результат и с display:inline; помощью too @tremby