Чистое решение HTML/CSS для выравнивания 3 элементов, когда 2 имеют динамический размер?
Этот вопрос требует пояснения. Пожалуйста, потерпите меня:
Несколько месяцев назад я создал заголовок из трех частей для раздела на веб-сайте. С левой стороны этого заголовка есть заголовок, содержание которого может меняться. Справа находится логотип, который всегда будет иметь ширину 150 пикселей и высоту 60 пикселей. Между ними множество двойных линий. Что-то вроде этого:
[ЭТО НАЗВАНИЕ] ============================================= [Логотип здесь]
Этот сайт отзывчивый, поэтому общая ширина заголовка является переменной.
Заголовок всегда должен быть на одной строке. Элемент div, содержащий двойные строки, должен изменить размер, чтобы заполнить пространство между заголовком и логотипом.
Первоначально я настроил его так, чтобы строки изменялись с помощью медиа-запросов и calc(); функция. Тем не менее, веб-сайт должен быть полностью совместим с IE 8, поэтому я написал несколько JS, чтобы заставить его работать.
Вот скрипка JS, которая по сути отражает это поведение: http://jsfiddle.net/55u5mpu2/2/
function sizeLines() {
var logoSize = document.getElementById("the-logo").offsetWidth;
var titleWidth = document.getElementById("the-h2-Title").offsetWidth;
var totalWidth = document.getElementById("entire-Header").offsetWidth;
var offsetWidth = (logoSize + titleWidth);
var linesWidth = (totalWidth - offsetWidth - 20) + "px";
document.querySelector("#the-lines").style.width = linesWidth; }
window.onresize = sizeLines;
#entire-Header{
position: relative;
width: 100%;
height:40px;
}
#the-h2-Title {
position: relative;
float: left;
width: auto;
padding-right: 10px;
}
#the-lines {
border-top: 4px solid #000000 !important;
border-bottom: 4px solid #000000 !important;
height: 1px;
float: left;
margin-top: 23px;
min-width: 40px;
}
#the-logo {
position: relative;
max-width: 160px;
max-height: 50px;
float: right;
width: auto;
height: auto;
top: 0;
}
<div id="entire-Header">
<h2 id="the-h2-Title">
<div id="headlineTextbox">This is a Test Headline</div>
</h2>
<div id="the-lines"> </div>
<img id="the-logo" src="http://placehold.it/150x60">
</div>
Проблема в том, что при медленных соединениях скрипту требуется много времени, поэтому логотип на некоторое время висит в странном месте. В результате я пытаюсь найти чисто CSS/HTML решение, чтобы сделать то же самое, что и мой скрипт.
Здесь есть связанные вопросы, но ни один из них не подходит. Я не могу указать ширину ни заголовка, ни строк, потому что они оба динамические.
Кажется, что таблицы работают нормально, но если я добавлю width: auto; на двух из tds вещи терпят неудачу.
Вот пример хорошего макета таблицы, который я создал: http://jsfiddle.net/d40a429s/1/
table {width: 100%;}
#test-title {width:20%;}
#lines-here {width:auto;}
#lines-here > div {border-top:4px solid #2a2a2a; border-bottom:4px solid #2a2a2a;height: 1px;}
#test-logo {width: 160px; padding-left: 10px;}
<div id="test-Section-Header">
<table>
<tbody>
<tr>
<td id="test-title"><h2>Test Title</h2></td>
<td id="lines-here">
<div></div>
</td>
<td id="test-logo">
<img src="http://placehold.it/150x60" alt="150 x 60 placeholder logo image">
</td>
</tr>
</tbody>
</table>
</div>
Я пытался поставить позицию: абсолют; и верхний / левый или верхний / правый на логотипе и заголовке, но я не могу заставить этот средний div правильно изменить размер.
Итак: если кто-то сделал это здесь: есть идеи о том, как я могу заставить это работать без JS? Или, может быть, способ привести в порядок мой JS, чтобы он работал быстрее?
Спасибо!
3 ответа
Ваша проблема может быть полностью решена с использованием HTML и CSS, слегка изменив их, без необходимости использования JavaScript.
Вот моя вилка скрипки Данилда - Поддерживает IE8+
Объяснение:
перемещение
#the-logo
быть первым элементом в#entire-Header
Контейнер позволяет нам плавать#the-logo
правильно, без обтекания и опускания ниже заголовка, потому что он имеет "более высокий приоритет" при расчете макета.Добавление "clearfix" к
#entire-Header
позволяет нам не беспокоиться о заголовке, переполняющем пространство, выделенное какими-либо фиксированными измерениями. Это освобождает нас, чтобы удалитьheight
ограничение в целом.#entire-Header
является элементом уровня блока (div
), что означает, что по умолчанию его ширина будет равна 100%, и его не нужно явно устанавливать (если только он не был переопределен ранее).#the-h2-Title
это второй элемент внутри#entire-Header
и плавает влево. Быть блок-элементом (h2
), обернем ниже#the-logo
в целом, прежде чем обернуть слова в себя.Теперь, когда у нас есть логотип и название, расположенное по обе стороны, мы можем стилизовать
#the-lines
, Будучи элементом уровня блока, он будет расширяться по горизонтали в доступное пространство, которое в этом случае составляет 100%. Чтобы предотвратить его расширение под заголовком и логотипом, мы добавляемoverflow: hidden
или жеoverflow: auto
в#the-lines
, Это создает новый контекст форматирования блока, который делает#the-lines
Ширина сужается до оставшегося доступного пространства, которое рассчитывается между двумя плавающими элементами.Предостережение: это будет работать только до тех пор, пока высота
#the-line
меньше, чем у#the-logo
, иначе#the-line
заверну ниже#the-logo
, Это потому, что это третий элемент, и на его расположение влияют первые два элемента.
CSS:
#entire-Header {
margin: 1em 0 .5em;
}
/* http://nicolasgallagher.com/micro-clearfix-hack/ */
#entire-Header:before,
#entire-Header:after {
content: " ";
display: table;
}
#entire-Header:after {
clear: both;
}
#the-h2-Title {
margin: .5em 0;
float: left;
margin-right: 10px;
}
#the-lines {
border-top: 4px solid #000000 !important;
border-bottom: 4px solid #000000 !important;
height: 1px;
/* http://www.stubbornella.org/content/2009/07/23/overflow-a-secret-benefit/ */
overflow: hidden;
margin-top: 23px;
}
#the-logo {
width: 160px;
height: 50px;
margin-left: 10px;
float: right;
}
Разметка:
<div id="entire-Header">
<img id="the-logo" src="http://placehold.it/150x60" />
<h2 id="the-h2-Title">
<div id="headlineTextbox">This is a Test Headline</div>
</h2>
<div id="the-lines"></div>
</div>
Это, безусловно, можно сделать с поддержкой IE8
1) Переместите фиксированную ширину + плавающее правое изображение, чтобы быть первым дочерним
2) Хранить float:left
в заголовке
3) Установить overflow:hidden
(или авто) в строках (чтобы установить новый контекст форматирования блока)
4) Установить display:inline-block
на контейнере (чтобы содержать поплавки)
Обновлена FIDDLE ( измените размер браузера, чтобы увидеть эффект)
#entire-Header {
display: inline-block;
width: 100%;
height: 40px;
}
#the-h2-Title {
float: left;
padding-right: 10px;
}
#the-lines {
border-top: 4px solid #000000 !important;
border-bottom: 4px solid #000000 !important;
height: 1px;
overflow: hidden;
margin-top: 23px;
}
#the-logo {
width: 160px;
height: 50px;
padding-left: 10px;
float: right;
}
<div id="entire-Header">
<img id="the-logo" src="http://placehold.it/150x60" />
<h2 id="the-h2-Title">
<div id="headlineTextbox">This is a Test Headline</div>
</h2>
<div id="the-lines"></div>
</div>
С поддержкой IE8
Если вы хотите сохранить поддержку IE8, вы можете исправить медленную загрузку, включив <script>
тег в HTML.
...
</div>
</div>
<script>
// JavaScript here
</script>
</body>
Без поддержки IE8 (IE10+)
Если вы хотите чисто CSS-решение, используйте flexbox. Сделайте заголовок флексбоксом, назначьте порядок заголовку, строке и логотипу и дайте линии сжиматься и увеличиваться при необходимости.
<!-- HTML -->
<div class="container">
<div class="title">
Title
</div>
<div class="line">
Line
</div>
<div class="logo">
Logo
</div>
</div>
/* CSS */
.container {
display: flex;
width: 100%;
}
.line {
order: 1;
flex-shrink: 10000000;
flex-grow: 10000000;
}
.title {
order: 0;
flex-shrink: 1;
}
.logo {
order: 2;
flex-shrink: 1;
}
Для получения дополнительной информации о flexbox см. Эту статью и эту полезную площадку flexbox.