как вы удерживаете родителей всплывающих элементов от разрушения?

<p>хотя такие элементы, как <code><div></code>s, обычно растут в соответствии со своим содержимым, использование свойства <code>float</code> может вызвать поразительную проблему для новичков в css: <strong>если у всплывающих элементов есть неплавающие родительские элементы, родительский элемент рухнет.</strong></p><p>например:</p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre class="snippet-code-html lang-html prettyprint-override"><code><div> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div></code></pre></div> </div><p>родительский div в этом примере будет <strong>не раскрываться</strong>, чтобы содержать его перемещенные потомки - он будет иметь <code>height: 0</code>.</p><h1>как вы решаете эту проблему?</h1><p><em> я хотел бы создать исчерпывающий список решений здесь. если вам известны проблемы совместимости с различными браузерами, укажите их. </em></p><h2>решение 1</h2><p>плыть родитель.</p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre class="snippet-code-html lang-html prettyprint-override"><code><div style="float: left;"> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div></code></pre></div> </div><p><strong>плюсы</strong>: семантический код.<br> <strong>минусы</strong>: возможно, вы не всегда хотите, чтобы родитель был плавающим. даже если вы это сделаете, вы пускаете в ход родителей родителей и так далее? должны ли вы плавать каждый элемент предка?</p><h2>решение 2</h2><p>дайте родителю явную высоту.</p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre class="snippet-code-html lang-html prettyprint-override"><code><div style="height: 300px;"> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div></code></pre></div> </div><p><strong>плюсы</strong>: семантический код.<br> <strong>минусы</strong>: не гибкий - при изменении содержимого или изменении размера браузера макет будет нарушен.</p><h2>решение 3</h2><p>добавьте элемент "spacer" внутри родительского элемента, например так:</p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre class="snippet-code-html lang-html prettyprint-override"><code><div> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> <div class="spacer" style="clear: both;"></div> </div></code></pre></div> </div><p><strong>плюсы</strong>: прямо к коду.<br> <strong>минусы</strong>: не семантически; spacer div существует только как макет взлома.</p><h2>решение 4</h2><p>установите для родителя значение <code>overflow: auto</code>.</p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code"> <pre class="snippet-code-html lang-html prettyprint-override"><code><div style="overflow: auto;"> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div></code></pre></div> </div><p><strong>плюсы</strong>: не требует дополнительного div.<br> <strong>минусы</strong>: похоже на хак - это не заявленная цель свойства <code>overflow</code>.</p><h1>комментарии? другие предложения?</h1>

<h2>решение 1:</h2><p>наиболее надежный и ненавязчивый метод выглядит так:</p><p>демо: <a href="http://jsfiddle.net/so\_amk/wxaeh/">http://jsfiddle.net/so\_amk/wxaeh/</a> </p><p>html:</p><pre><code><div class="clearfix"> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div> </code></pre><p>css:</p><pre><code>.clearfix::after { content: " "; display: block; height: 0; clear: both; } </code></pre><p>с небольшим таргетингом css вам даже не нужно добавлять класс к родительскому <code>div</code>.</p><p>это решение обратно совместимо с ie8, поэтому вам не нужно беспокоиться о сбое старых браузеров.</p><h2>решение 2:</h2><p>была предложена адаптация к решению 1, и она выглядит следующим образом:</p><p>демо: <a href="http://jsfiddle.net/wxaeh/162/">http://jsfiddle.net/wxaeh/162/</a> </p><p>html:</p><pre><code><div class="clearfix"> <div style="float: left;">div 1</div> <div style="float: left;">div 2</div> </div> </code></pre><p>css:</p><pre><code>.clearfix::after { content: " "; display: block; height: 0; clear: both; *zoom: expression( this.runtimestyle['zoom'] = '1', this.innerhtml += '<div class="ie7-clear"></div>' ); } .ie7-clear { display: block; clear: both; } </code></pre><p>это решение кажется обратно совместимым с ie5.5, но не проверено.</p><h2>решение 3:</h2><p>также можно установить <code>display: inline-block;</code> и <code>width: 100%;</code>, чтобы эмулировать обычный элемент блока, не сворачиваясь.</p><p>демо: <a href="http://jsfiddle.net/so\_amk/ae5ey/">http://jsfiddle.net/so\_amk/ae5ey/</a> </p><p>css:</p><pre><code>.clearfix { display: inline-block; width: 100%; } </code></pre><p>это решение должно быть обратно совместимо с ie5.5, но было протестировано только в ie6.</p>

<p>я обычно использую трюк <code>overflow: auto</code>; хотя это, строго говоря, не предполагаемое использование для переполнения, оно <em>есть</em> своего рода связанное - достаточно, чтобы его было легко запомнить, конечно. значение самого <code>float: left</code> было расширено для различных применений более значительно, чем переполнение в этом примере, imo.</p>

<p>вместо того, чтобы ставить <code>overflow:auto</code> на родителя, поместите <code>overflow:hidden</code></p><p>первый css, который я пишу для любой веб-страницы:</p><pre><code>div { overflow:hidden; } </code></pre><p>тогда мне никогда не придется беспокоиться об этом.</p>

<p>проблема возникает, когда плавающий элемент находится внутри коробки контейнера, этот элемент не заставляет автоматически корректировать высоту контейнера в зависимости от плавающего элемента. когда элемент является плавающим, его родительский элемент больше не содержит его, потому что он удален из потока. вы можете использовать 2 метода, чтобы исправить это:</p><ul> <li><code>{ clear: both; }</code></li> <li><code>clearfix</code></li> </ul><p>как только вы поймете, что происходит, используйте метод ниже, чтобы "очистить" его.</p><pre><code>.clearfix:after { content: "."; display: block; clear: both; visibility: hidden; line-height: 0; height: 0; } .clearfix { display: inline-block; } html[xmlns] .clearfix { display: block; } * html .clearfix { height: 1%; } </code></pre><p><strong> <a href="http://www.webtoolkit.info/demo/css-clearfix">демонстрация:)</a> </strong></p>

<p>существует несколько версий исправления: <strong> <a href="https://github.com/necolas">николас галлахер</a> </strong> и <strong> <a href="https://twitter.com/thierrykoblentz">тьерри кобленц</a> </strong> в качестве ключевых авторов.</p><p>если вам нужна поддержка более старых браузеров, лучше всего использовать следующее исправление:</p><pre><code>.clearfix:before, .clearfix:after { content: ""; display: table; } .clearfix:after { clear: both; } .clearfix { *zoom: 1; } </code></pre><p>в scss вы должны использовать следующую технику:</p><pre><code>%clearfix { &:before, &:after { content:" "; display:table; } &:after { clear:both; } & { *zoom:1; } } #clearfixedelement { @extend %clearfix; } </code></pre><p>если вам не нужна поддержка старых браузеров, есть более короткая версия:</p><pre><code>.clearfix:after { content:""; display:table; clear:both; } </code></pre>

<p>хотя код не является полностью семантическим, я думаю, что более просто иметь то, что я называю "очищающим div" внизу каждого контейнера с плавающими в нем. фактически, я включил следующее правило стиля в свой блок сброса для каждого проекта:</p><pre><code>.clear { clear: both; } </code></pre><p>если вы разрабатываете стили для ie6 (да поможет вам бог), вы можете также назначить этому правилу высоту строки и высоту 0px.</p>

<p>странно, еще никто не придумал полного ответа на это, ну что ж, вот оно.</p><h2>решение первое: <em> ясно: оба </em></h2><p>добавление элемента блока со стилем clear: both; на него будут очищены плавающие объекты после этой точки и остановлен родительский элемент этого элемента. <a href="http://jsfiddle.net/tvd2x/1/">http://jsfiddle.net/tvd2x/1/</a> </p><p>плюсы: позволяет очистить элемент и добавленные ниже элементы не будут зависеть от всплывающих элементов выше и действительных css.</p><p>минусы: требуется еще один тег, чтобы очистить поплавки, вздутие живота разметки.</p><p>примечание. чтобы вернуться к ie6 и работать с воздерживающимися родителями (т. е. с элементом ввода), вы не можете использовать: after.</p><h2>решение второе: <em> display: table </em></h2><p>добавление дисплея: таблица; к родителю, чтобы он отмахнулся от поплавков и отображается с правильной высотой. <a href="http://jsfiddle.net/h9gaz/1/">http://jsfiddle.net/h9gaz/1/</a> </p><p>плюсы: без дополнительной разметки и намного аккуратнее. работает в ie6 +</p><p>минусы: требуется неверный css, чтобы убедиться, что все хорошо в ie6 и 7.</p><p>примечание: ie6 и 7 width auto используются для предотвращения ширины 100% + отступы, что не имеет место в более новых браузерах.</p><h2>заметка о других "решениях"</h2><p>эти исправления возвращают браузер с наименьшей поддерживаемой поддержкой, более 1% использования в глобальном масштабе (ie6), что означает использование: after не обрезает его.</p><p>скрытое переполнение показывает содержимое, но не предотвращает свертывание элемента и поэтому не отвечает на вопрос. использование встроенного блока может привести к ошибкам, у детей со странными полями и т.д. таблица намного лучше.</p><p>установка высоты "предотвращает" коллапс, но не является правильным решением.</p><h2>неверный css</h2><p>неверные css никогда никому не причиняют вреда, на самом деле, сейчас это норма. использование префиксов браузера так же недопустимо, как использование взломов, специфичных для браузера, и никак не влияет на конечного пользователя.</p><h2>в заключение</h2><p>я использую оба вышеупомянутых решения, чтобы элементы правильно реагировали и играли друг с другом, умоляю вас сделать то же самое.</p>

<p>идеальным решением было бы использовать <code>inline-block</code> для столбцов вместо плавающих. я думаю, что поддержка браузера довольно хороша, если вы будете следовать (а) применять <code>inline-block</code> только к элементам, которые обычно встроены (например, <code>span</code>); и (б) добавить <code>-moz-inline-box</code> для firefox.</p><p>проверьте свою страницу и в ff2, потому что у меня было множество проблем при вложении определенных элементов (удивительно, это тот случай, когда ie работает намного лучше, чем ff).</p>

<p>я использую 2 и 4, где это применимо (т.е. когда я знаю высоту содержимого или если переполнение не вредит). в другом месте я остановлюсь на решении 3. кстати, ваше первое решение не имеет преимущества перед 3 (что я могу заметить), потому что оно больше не семантическое, поскольку оно использует тот же элемент-пустышку.</p><p>кстати, я не буду беспокоиться о том, что четвертое решение - взлом. взломы в css будут вредны только в том случае, если их базовое поведение будет подвергаться реинтерпретации или другим изменениям. таким образом, ваш хак не будет гарантированно работать. однако в этом случае ваш хак зависит от того, какое поведение <code>overflow: auto</code> предназначено. никакого вреда в том, чтобы подключить бесплатную поездку.</p>

<p>мой любимый метод использует класс clearfix для родительского элемента</p><pre><code>.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .clearfix { display: inline-block; } * html .clearfix { height: 1%; } .clearfix { display: block; } </code></pre>

<p>одним из наиболее известных решений является вариант вашего решения № 3, в котором вместо несемантического html-элемента используется псевдоэлемент.</p><p>это выглядит примерно так...</p><pre><code>.cf:after { content: " "; display: block; visibility: hidden; height: 0; clear: both; } </code></pre><p>вы помещаете это в свою таблицу стилей, и все, что вам нужно, это добавить класс 'cf' к элементу, содержащему числа с плавающей точкой.</p><p>то, что я использую, является другим вариантом, который прибывает из николаса галлахера.</p><p>он делает то же самое, но он короче, выглядит аккуратнее и, возможно, используется для выполнения еще одной довольно полезной задачи - предотвращения сужения полей дочерних элементов со своими родителями (но для этого вам нужно что-то еще - узнайте больше об этом здесь <a href="http://nicolasgallagher.com/micro-clearfix-hack/">http://nicolasgallagher.com/micro-clearfix-hack/</a> ).</p><pre><code>.cf:after { content: " "; display: table; clear: float; } </code></pre>

<p>добавить это в родительском div внизу</p><pre><code> <div style="clear:both"></div> </code></pre>

<p>другое возможное решение, которое я считаю более семантически правильным, состоит в том, чтобы изменить плавающие внутренние элементы на "display: inline". этот пример и то, над чем я работал, когда натолкнулся на эту страницу, используют плавающие дивы почти так же, как и диапазон. вместо того, чтобы использовать div, переключитесь на span или, если вы используете другой элемент, который по умолчанию "display: block" вместо "display: inline", измените его на "display: inline". я считаю, что это 100% семантически правильное решение.</p><p>решение 1, плавающее родительский, по сути, чтобы изменить весь документ, который будет перемещен.</p><p>решение 2, устанавливающее явную высоту, похоже на рисование прямоугольника и высказывание, что я хочу разместить изображение здесь, то есть использовать это, если вы делаете тег img.</p><p>решение 3, добавив пробел к clear float, похоже на добавление дополнительной строки под вашим контентом и также будет мешать с окружающими элементами. если вы используете этот подход, вы, вероятно, захотите установить для div высоту 0px.</p><p>решение 4, переполнение: авто, подтверждает, что вы не знаете, как выложить документ, и вы признаете, что не знаете, что делать.</p>

<p>основная проблема, с которой вы можете столкнуться при изменении переполнения на <code>auto</code> или <code>hidden</code>, заключается в том, что все может стать прокручиваемым с помощью средней кнопки мыши, и пользователь может испортить весь макет сайта.</p>

<p>я считаю, что лучший способ - установить <code>clear:both</code> для следующего элемента.</p><p>вот почему:</p><p>1) селектор <code>:after</code> не поддерживается в ie6/7 и глючит в ff3, однако<br> , если вы заботитесь только о клиринге ie8 + и ff3.5 + с: after, вероятно, лучше для вас ...</p><p>2) <code>overflow</code> должен делать что-то еще, поэтому этот хак недостаточно надежен.</p><p>примечание для автора: нет ничего хакерского при очистке ... очистка означает пропуск плавающих полей. clear с нами, так как html3 (кто знает, может быть, даже дольше) <a href="http://www.w3.org/markup/html3/deflists.html">http://www.w3.org/markup/html3/deflists.html</a> , возможно, им следует выбрать несколько другое имя, например page: новый, но это только деталь ...</p>