Текучие колонки CSS, фиксированные поля; Святой Грааль Святого Грааля - PullRequest
48 голосов
/ 25 августа 2011

Обновление и резюме

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

( Кроме того, я почти уверен, что это будет ребенокиграть, когда поддерживается * единица измерения calc() CSS3, делая что-то вроде width: calc(25% - 5px), хотя, вероятно, к этому моменту мы будем просматривать Интернет в наших умах )

Я работаю надCSS-фреймворк для нескольких проектов, которые разделяют требования дизайна;а именно макет колонны жидкости 12.Используя плавающие элементы .column с шириной в процентах (100% / 12) x col_size, это достаточно просто.Однако проблема заключается в добавлении фиксированных полей ( или любого другого расстояния ) между столбцами.

В моей первоначальной попытке использовались столбцы жидкости, как описано, с вложенным дочерним элементом .panelв каждом.Далее следует фрагмент HTML / CSS ( сокращено для краткости ):

.column{
    float: left;
    display: inline-block;
}

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */

.panel{
    width: 100%;
    padding: 5px;
    box-sizing: border-box; /* so padding doesn't increase width */
}
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-03">
    <div class="panel">Width-03</div>
</div>
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-05">
    <div class="panel">Width-05</div>
</div>

Этот фрагмент создаст макет, аналогичный приведенному ниже изображению, однако все элементы .panel имеют5px набивка со всех сторон. Я пытаюсь сделать края содержимого внешних столбцов на одном уровне с краем порта просмотра ( или родительского контейнера в этом отношении ) .Другой подход заключается в том, чтобы полностью исключить класс .panel и использовать только столбцы:

.column{
    float: left;
    display: inline-block;
    padding-left: 10px;
    box-sizing: border-box;
}

.column:first-child{ padding-left: 0px; }

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */
<div class="column width-02">Width-02</div>
<div class="column width-03">Width-03</div>
<div class="column width-02">Width-02</div>
<div class="column width-05">Width-05</div>

Опять же, это работает хорошо, получая результаты, даже более близкие к изображению нижеоднако теперь ( фактическая ) проблема заключается в том, что заполнение поглощает ширину столбцов, обворовывая распределение ширины.Столбец :first-child имеет на 10 пикселей ( или независимо от размера поля ) большую ширину области содержимого, чем его братья и сестры.

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

И так, независимо от того, используются ли отступы, поля или некоторые их комбинацииЕсть ли какое-либо решение для жидкостных колонн с фиксированными полями, с равномерным распределением пространства желоба, которое не отнимает «маргинальную» (*** хаха *) область содержимого от соседних колонок? **


Оригинальный вопрос

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

Есть ли способ, используя чистый CSS, добиться создания колонного макета с изменяемой шириной и фиксированной шириной полей?

Важное примечание : эта цифра является лишь примером, а не конкретным макетом, которого я хочу достичь.Данное решение должно разрешать любую комбинацию соседних столбцов, общее распределение ширины которых должно составлять 12 или менее.Для справки рассмотрим популярную сетку 960 .

super_awesome_layout.css
Примечание : в 12-колоночном макете распределение шириныстолбцов на изображении соответственно 2, 3, 2 и 5.

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

width: 100%;
box-sizing: border-box;
padding: 10px;

Это опять же почти, отлично;проблема с этим подходом заключается в том, что первый и последний столбцы имеют внешние «поля» (10px), а «поля» между каждым столбцом удваиваются (2 x 10px)

Конечно, с включением нового типа значения CSS3 calc() это может быть решено намного проще.Что-то в направлении:

.width-12 > .panel{ width: 100%; }
.width-09 > .panel{
    width: calc(75% - 10px);
    margin: ...;
}

У меня есть некоторые исправления Javascript, я взломал некоторые вещи, которые «работают», но я в поиске.Надеюсь, существует самый святой из Граалей.

Следующее решение и предоставленное @avall (хотя, безусловно, хороший выбор для упрощения), к сожалению, не то, что я ищу. Основная проблема заключается в том, что поля не распределяются равномерно по столбцам.

Единственный способ увидеть эту работу - это уменьшить отступ .panel до 5px и что-то вроде:

.column:first-child > .panel {
    padding-left: 0px;
}

.column:last-child > .panel {
    padding-right: 0px;
}

/* not necessary? in any case, haven't tested */
.column:only-child > .panel {
    padding-right: 0px;
    padding-left: 0px;
}

Это решение неприемлемо, только потому, что IE8 не может распознать :last-child ( и в этом отношении :only-child) псевдо-селекторы.

Ответы [ 10 ]

64 голосов
/ 31 августа 2011

Я наконец понял. После сотен часов, потраченных впустую и выключенных за последнее десятилетие (хотя я полагаюсь на некоторые CSS, которые не работали бы год назад в любом случае). Я решил это без каких-либо ошибок. и в IE8 +.

Пожалуйста, подготовьте 2001: Музыка Космической Одиссеи, потому что я приземляюсь на эту лодку.

Гениальность и хитрость этого метода заключается в использовании элементов встроенного блока, а затем в использовании межсловного пространства для уравновешивания с использованием отрицательного правого поля. Отрицательное правое поле само по себе объединит элементы, позволяя вам установить ширину 100% и по-прежнему размещать объекты между ними, но оставляя элементы перекрывающимися. Установка отрицательного поля на родительском элементе просто отменяет дочернее поле в отношении эффекта взаимодействия с общей шириной (магическая метка «100% ширины», которую мы пытаемся ударить »). Заполнение служит только для увеличения размера элемента. и бесполезен в отношении противодействующего запаса. Он часто используется с определением размеров ячеек в сфальсифицированных решениях этой проблемы присяжными, за счет потери возможности использовать отступы вообще (и запас) и, вероятно, требует большего элементы обертки.

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

Я смиренно представляю окончательный ответ на проблему гибких колонн с фиксированными желобами. Настоящим я называю свое решение "маневр омега". Он имеет возможность обрабатывать произвольные столбцы смешанной ширины (добавляя до 100% общей ширины точно или чуть меньше для округления), любой размер желоба, любое заранее заданное количество столбцов по ширине, обрабатывает произвольное количество строк с автоматическим переносом и использует элементы inline-block, поэтому предоставляет опции вертикального выравнивания, которые поставляются с inline-block, и не требует дополнительной разметки и требует только одного объявления класса в контейнере (не считая определения ширины столбцов). Я думаю, что код говорит сам за себя. Вот реализация кода для 2-6 столбцов с использованием желобов 10px и классов вспомогательных бонусов для процентов.

РЕДАКТИРОВАТЬ: интересная головоломка. Мне удалось получить две немного разные версии; один для mozilla и ie8 +, другой для webkit. Кажется, трюк с переносом слов не работает в webkit, и я не знаю, почему другая версия работает в webkit, а не ie8 + / mozilla. Сочетание обоих дает вам охват всему, и я готов поспорить, что есть способ объединить эту тактику или что-то очень похожее для обхода проблемы.

РЕДАКТИРОВАТЬ 2: В основном получил это! Волшебный text-align: justify почти полностью использует WebKit вместе с межсловным интервалом. Пространство кажется совсем незначительным, например, в пикселях справа и, возможно, в лишних желобах. Но это удобно и кажется более надежным в хранении столбцов, чем все, что я использовал раньше. Он никогда не сокращает количество столбцов, он будет сжиматься, пока браузер не получит горизонтальную полосу прокрутки.

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

РЕДАКТИРОВАТЬ 4: Получил ответ IE от некоторых других сообщений ширины: -ms-text-justify: distribute-all-lines. Протестировано в IE8-10.

/* The Omega Maneuver */
[class*=cols] { text-align: justify; padding-left: 10px; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class*=cols]>* { display: inline-block; text-align: left; font-size: 13px;
                word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { word-spacing: 20px; padding-right: 20px; }
.cols3 { word-spacing: 30px; padding-right: 30px; }
.cols4 { word-spacing: 40px; padding-right: 40px; }
.cols5 { word-spacing: 50px; padding-right: 50px; }
.cols6 { word-spacing: 60px; padding-right: 60px; }

  .cols2 > * { margin-right: -10px; }
  .cols3 > * { margin-right: -20px; }
  .cols4 > * { margin-right: -30px; }
  .cols5 > * { margin-right: -40px; }
  .cols6 > * { margin-right: -50px; }

Некоторые помощники:

.⅛, .⅛s >* { width: 12.50%; }
.⅙, .⅙s >* { width: 16.66%; }
.⅕, .⅕s >* { width: 20.00%; }
.¼, .¼s >* { width: 25.00%; }
.⅓, .⅓s >* { width: 33.00%; }
.⅜, .⅜s >* { width: 37.50%; }
.⅖, .⅖s >* { width: 40.00%; }
.½, .½s >* { width: 50.00%; }
.⅗, .⅗s >* { width: 60.00%; }
.⅝, .⅝s >* { width: 62.50%; }
.⅔, .⅔s >* { width: 66.00%; }
.¾, .¾s >* { width: 75.00%; }
.⅘, .⅘s >* { width: 80.00%; }
.⅚, .⅚s >* { width: 83.33%; }
.⅞, .⅞s >* { width: 87.50%; }
.blarg-five-twelfs { width: 41.66%; }

Здесь вы можете увидеть мой опус магнума в действии среди поля славы: http://jsfiddle.net/xg7nB/15/

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

Абсолютно минимальная реализация, использующая в качестве примера 4 одинаковых по ширине (25%) ширины столбцов и 10px желобов, выглядит следующим образом:

.fourEqualCols { word-spacing: 40px; padding: 0 40px 0 10px;
                 text-align: justify; font-size: 0;
                 -ms-text-justify: distribute-all-lines; }

.fourEqualCols>* { margin-right: -30px; width: 25%;
                   display: inline-block; word-spacing: normal;
                   text-align: left; font-size: 13px; }


<div class="fourEqualCols ">
  <div>GLORIOUSLY CLEAN MARKUP</div>
  <div>I hate extra markup and excessive class props</div>
  <div>Naked code</div>
  <div>get intimate</div>
</div>

Тааак этот код, по сути, заменяет практически любой существующий каркас, верно? Если вы можете произвольно устанавливать желоба, а затем просто создавать наборы столбцов, которые достигают 100% ширины, это на самом деле строго превосходит большинство / все сеточные структуры, не так ли? Если вы больше не разрабатываете для IE7, как многие из нас, то это в сочетании с изменением размеров блока: border-box отдает отступы и border также не проблема.

Редактировать: о, верно, вы хотели быть заподлицо со сторонами контейнера. Никаких проблем с этим, мне пришлось специально добавлять боковые желоба, чтобы мы могли просто изменить некоторые значения на 10 и избавиться от отступов и вуаля. http://jsfiddle.net/bTty3/

[class^=cols] { text-align: justify; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class^=cols] >* { display: inline-block; text-align: left; font-size: 13px;
                word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { word-spacing: 20px; padding-right: 10px; }
.cols3 { word-spacing: 30px; padding-right: 20px; }
.cols4 { word-spacing: 40px; padding-right: 30px; }
.cols5 { word-spacing: 50px; padding-right: 40px; }
.cols6 { word-spacing: 60px; padding-right: 50px; }
 .cols2 >* { margin-right: 0 }
 .cols2 >* { margin-right: -10px; }
 .cols3 >* { margin-right: -20px; }
 .cols4 >* { margin-right: -30px; }
 .cols5 >* { margin-right: -40px; }
 .cols6 >* { margin-right: -50px; }

То же HTML

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

I beat CSS here's your proof

8 голосов
/ 26 августа 2011

Попробуйте это чистое решение CSS2: демонстрационная скрипка

Базовый CSS ( скрипка безкосметика) :

html, body {
    padding: 0;
    margin: 0;
}
#wrap {
    padding-right: 30px;
    overflow: hidden;
}
.col {
    float: left;
    margin-left: 40px;
    margin-right: -30px;
}
.col:first-child {
    margin-left: 0;
}
.small {
    width: 16.66%;
}
.medium {
    width: 25%;
}
.large {
    width: 41.66%;
}

HTML:

<div id="wrap">
    <div class="col small"></div>
    <div class="col medium"></div>
    <div class="col small"></div>
    <div class="col large"></div>
</div>

Протестировано на Win7 в IE7, IE8, IE9, Opera 11.50, Safari 5.0.5,FF 6.0, Chrome 13.0.


Обновление:

Теперь, если вам нравится работать с произвольным числом столбцов, вам нужно добавить дополнительный класс в контейнер, указавколичество столбцов:

<div class="cols-12 count-04">
    <div class="col width-02"></div>
    <div class="col width-03"></div>
    <div class="col width-02"></div>
    <div class="col width-05"></div>
</div>

См. эту обновленную скрипку , демонстрирующую количество различных столбцов.

Возможная ошибка:

Теоретически, imho, это решение должно работать для любого количества столбцов для каждой возможной минимальной ширины столбца в любой ширине окна браузера.Но, похоже, все браузеры не способны обрабатывать: 1. большое количество столбцов шириной в 1 столбец или 2. небольшую ширину окна браузера.

Обратите внимание, что все браузеры с минимальной шириной 1440 пикселей, что в 12 раз превышает 120 пикселей (пространство, занимаемое всеми полями в 10 пикселей), отлично справляется с решением.А при использовании двух или более столбцов ширины столбца требование минимальной ширины браузера действительно падает до 720 пикселей (6 * 120 пикселей).Последний случай звучит более реалистично, но все же я не могу объяснить это поведение браузера.

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

Я хотел бы услышать об этом от других экспертов CSS, так чтоЯ добавил награду.

7 голосов
/ 25 августа 2011

Почему бы вам не использовать

.column > .panel {
    padding: 10px 0 10px 10px;
}

.column:first-child > .panel {
    padding-left: 0px;
}

Это сделает 10px пробелов только между полями и без использования last-child.

2 голосов
/ 03 мая 2012

В отношении первоначального вопроса «Есть ли какой-либо способ, используя чистый CSS, достичь колонного макета с плавной шириной и фиксированной шириной полей?»

Удивительно, насколько чрезвычайно сложным становится CSS с такими видамивопросы.На прошлой неделе я работал над «базовым шаблоном» для создания собственного «святого Грааля», включая границы, поля и отступы ... Кажется, что CSS не подходит для подобных вопросов.Хотя этот вопрос довольно прост, его становится (почти?) Невозможно достичь в CSS, особенно в кросс-браузерном режиме.

Самое смешное, что эти вопросы легко решаются с помощью таблиц.Я не понимаю, почему веб-сообщество заставляет нас использовать div вместо таких неясных аргументов, как «семантика» и «простой обзор», поскольку большинство аргументов являются слабыми или даже ложными.Люди, которые говорят, что таблицы доставляют больше хлопот, явно не понимают реальных трудностей, связанных с CSS.

В любом случае, если вы хотите иметь структуру таблицы (поскольку столбцы являются частью таблицы), я предлагаю использовать'display: table'.

Чтобы получить изображение под исходным вопросом с чистым CSS, можно использовать следующее:

CSS

html,body{
    margin: 0px; 
    padding: 0px; 
    height: 100%; 
    width: 100%;
    overflow: auto;
}
.table{
    background: pink;
    display: table;
    width: 100%;
    height: 100%;
}
.tableRow{
    display: table-row;         
}
.tableCell{
    display: table-cell;
    vertical-align: top;
    height: 100%;  
}
/*
    Ensures the full size of the table-cell has the behaviour of a block-element. 
    This is needed, because 'table-cell' will behave differently in different browsers.
*/
.tableCell>div{
    height: 100%;
}
/*
    Padding has to be used instead of margin in 'border-box' modus.
*/
.tableCell>div>div{
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}
/*
    The final content.
*/
.tableCell>div>div>div{
    background: lightblue;
    padding: 5px;
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}


#col1{
    width: 16.66%;          
}
#col1>div>div{
    padding-right: 10px;
}
#col2{
    width: 25%;         
}
#col2>div>div{
    padding-right: 10px;
}
#col3{      
    width: 16.66%;
}
#col3>div>div{
    padding-right: 10px;
}
#col4{
    width: 41.66%;
}

HTML

<div class="table">
    <div class="tableRow">
        <div id='col1' class="tableCell">   
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col2' class="tableCell">
            <div><div><div>25%</div></div></div>
        </div>
        <div id='col3' class="tableCell">
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col4' class="tableCell">
            <div><div><div>41.66%</div></div></div>
        </div>  
    </div>
</div>

Я бы сказал, что использование дополнительных div для простоты просто перестаралось, но, к сожалению, CSS не имеет модели 'margin-box', котораяна самом деле решит миллиард проблем.

Такое количество вложенного кода может заставить вас задуматься: «Почему бы не использовать другие методы?»поскольку это может привести к меньшему количеству кода.Для очень конкретного желания это было бы так.Однако другие методы часто включают в себя плавающее или абсолютное позиционирование.Эти методы не могут достичь одного и того же: например, плавающие элементы могут иметь одинаковые по длине столбцы, но когда вам понадобится граница или поле, вы окажетесь в беде.Для абсолютного позиционирования это больше похоже на обратное: вы можете решить проблему наценки, но высота может быть основана только на одном столбце.

По моему мнению, CSS не соответствует требованиям.Несмотря на то, что все таблицы заменены на positiong, после всех этих лет все еще невозможно получить те же результаты.Достигнуть структуры таблиц «Святой Грааль Святого Грааля» - не просто самый простой способ, но и единственный способ… по крайней мере, насколько я знаю, после попытки сотен возможностей.

Остальныевопрос: зачем использовать div, если вы используете их как таблицы?Я не до конца понимаю это, но у людей, кажется, есть свои причины для этого.

2 голосов
/ 31 августа 2011

Посмотрите ответ тридцатки в этой теме для чистого CSS / HTML (жидкая компоновка с одинаково расположенными «столбцами» без JavaScript) ...

Ширина жидкости с одинаково расположенными DIVs

http://jsfiddle.net/thirtydot/EDp8R/

Модификация JSFiddle демонстрирует, что «столбцы» могут иметь различную фиксированную ширину и при этом иметь одинаковые и плавные поля.

http://jsfiddle.net/EDp8R/43/

Затем, наконец, еще один пример, использующий проценты при сохранении равных и плавных полей.

http://jsfiddle.net/EDp8R/45/

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

1 голос
/ 02 февраля 2012

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

Например:

/* Gutters */
h1, h2, h3, h4, h5, h6,
p, ul, ol, blockquote,
hr, address, pre, object, fieldset
{
    margin-right: .75rem;
    margin-left: .75rem;
    padding-right: .75rem;
    padding-left: .75rem;
}

Это также упрощает определение размеров столбцов, вложение и применение фонов к элементам lego.

1 голос
/ 01 сентября 2011

Я использую сетку OOCSS для этого

https://github.com/stubbornella/oocss

Я недавно выложил демо-версию онлайн на своем собственном сайте, так как в сети нет подходящих примеров: (

http://www.leipeshit.com/awesome_stuff/oocss/core/grid/grids_all.html

0 голосов
/ 15 января 2015

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

Например: использование pureCSS pure-g - это внешний контейнер, pure-u- * - это узел столбца (display: inline-block), содержащий вложенный div. интервал - это имя этого пользовательского расширения системы сетки pureCSS, позволяющего использовать поля столбцов.

.pure-g.spacing {
    margin: 0 -10px;
}

.pure-g.spacing [class *= "pure-u"] > div {
    margin: 10px;
}

Должно работать в большинстве браузеров. Скажите, если нет - я уже его использую.

С уважением, Max

0 голосов
/ 06 января 2015

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

Это не использует JavaScript и работает в IE8 +.

В этом решении маржа определяется для двух классов - поэтому ее легко изменить для адаптивных дизайнов. Ширина столбцов также представляет пространство, которое они используют, например, строка из 2 столбцов имеет ширину 50%, а строка из 4 столбцов имеет ширину 25%.

Вы можете увидеть пример на http://www.andrewjamestait.co.uk/conflexgrids/

Или он доступен на GitHub по адресу https://github.com/andrewjtait/conflexgrids

0 голосов
/ 11 марта 2013

Почему бы не использовать заполнение, как в первом примере, а затем установить box-sizing: border-box для всех элементов?

...