CSS: два столбца

Я не могу понять, как добиться следующего макета с помощью CSS (вероятно, потому, что я на самом деле не знаю CSS).

У меня есть куча таких div:

<div class = "right"> <p>1</p> </div>
<div class = "left">  <p>2</p> </div>
<div class = "left">  <p>3</p> </div>
<div class = "left">  <p>4</p> </div>
<div class = "right"> <p>5</p> </div>
<div class = "right"> <p>6</p> </div>

(не настоящее содержимое)

Теперь я хочу, чтобы макет выглядел как два равных столбца div, с «правыми» справа и «левыми» слева, таким образом:

2 1
3 5
4 6

[Обновлено: в предыдущей версии этого вопроса у меня были текстовые поля внутри div, и все div имели разные имена, такие как «one» и «xyz».] Я пробовал что-то вроде

div.right { width:50%; float:right; clear:right; }
div.left { width:50%; float:left; clear:left;}

но это не совсем работает: он производит что-то вроде:

2 1
3 
4 5
  6

(без "чистых" s, он беспечно производит

2 1
3 4
6 5

что не то, что нужно).

Очевидно, что его можно заставить работать, если блоки div упорядочены по-другому, но я бы не хотел этого делать (потому что эти div генерируются динамически, если в браузере есть Javascript, и я не хочу менять фактический порядок который отображается в отсутствие Javascript по семантическим причинам). Можно ли получить желаемый макет?

[Как бы то ни было, я хочу, чтобы это не работало в IE или более старых версиях других браузеров, поэтому, если есть решение, которое работает только в браузерах, совместимых со стандартами, ничего страшного :-)]

Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
3
0
2 514
11

Ответы 11

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

Нет, он не работает без "clear" - он производит совсем другое.

ShreevatsaR 13.12.2008 20:08

Вы пытаетесь разделить входной поток на два независимых потока, и я не думаю, что CSS позволяет вам это сделать. Использование левого и правого поплавков - отличная идея, но она не всегда работает. Спецификация CSS говорит в правиле 5 9.5.1:

The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.

Итак, ваши поплавки могут прыгать влево, вправо и вниз, но не вверх.

Вы можете добиться всего с помощью абсолютного позиционирования, но в этом нет ничего автоматического.

Обновлено: в комментариях я сказал, что не ожидаю, что CSS3 будет поддерживать такую ​​функцию, потому что она нарушает разделение содержимого и макета. Позже я вспомнил, что CSS3 планирует добавить сноски. Итак, если вы пометите некоторые из ваших div с помощью «float: note», выбранные div переместятся в отдельную область «сноски» страницы. Думаю, вы можете разместить их справа от остальной части макета.

Хорошее описание моей проблемы, спасибо. Может быть, есть что-нибудь в CSS3?

ShreevatsaR 13.12.2008 20:29

В css (не только css3) вы можете делать такие вещи, как "display: table-cell;" Это даст вам именно то, что вы хотите.

dave mankoff 13.12.2008 20:32

Насколько я знаю, нет. Можно возразить, что то, что вы хотите, изменяет структуру / содержимое документа и, таким образом, выходит за рамки полномочий CSS, которые должны изменять только представление.

buti-oxa 13.12.2008 20:35

В Firefox 3 у меня работает следующее:

div {
  width: 198px;
  border: 1px solid black;
}
div.onediv, div.tendiv, div.xyzdiv { float: right; }
div.twodiv, div.abcdiv, div.pqrdiv { float: left; }
<div style = "width: 400px;">
  <div class = "onediv"><p>One name</p> <textarea id = "one"></textarea></div>
  <div class = "twodiv"><p>Two name</p> <textarea id = "two"></textarea></div>
  <div class = "tendiv"><p>Ten name</p> <textarea id = "ten"></textarea></div>
  <div class = "abcdiv"><p>Abc name</p> <textarea id = "abc"></textarea></div>
  <div class = "xyzdiv"><p>Xyz name</p> <textarea id = "xyz"></textarea></div>
  <div class = "pqrdiv"><p>Pqr name</p> <textarea id = "pqr"></textarea></div>
</div>

Просто небольшое примечание: размещение div внутри имени вашего класса (например, abcdiv) немного избыточно и странно. Не вдаваясь в громкую обличительную речь о правильном использовании классов, я бы не стал это делать.

Вы действительно можете упростить свой код, если просто скажете «col1» и «col2». Таким образом, вы даже можете поменять столбцы позже, если захотите:

div {
  width: 198px;
  border: 1px solid black;
}
div.col1 { float: right; }
div.col2 { float: left; }
<div style = "width: 400px;">
  <div class = "col1"><p>One name</p> <textarea id = "one"></textarea></div>
  <div class = "col2"><p>Two name</p> <textarea id = "two"></textarea></div>
  <div class = "col1"><p>Ten name</p> <textarea id = "ten"></textarea></div>
  <div class = "col2"><p>Abc name</p> <textarea id = "abc"></textarea></div>
  <div class = "col1"><p>Xyz name</p> <textarea id = "xyz"></textarea></div>
  <div class = "col2"><p>Pqr name</p> <textarea id = "pqr"></textarea></div>
</div>

Спасибо. (И да, я опущу «div» в именах классов :)) Так что же «198px», потому что это «400px / 2 - 1px»? И можно ли сделать так, чтобы он занимал всю ширину страницы вместо 400 пикселей?

ShreevatsaR 13.12.2008 19:46

да, он только поместил границы, чтобы показать вам макет (я думаю), поэтому, если вы установите border: 0px, вы можете получить 400px

inspite 13.12.2008 19:52

Ага. Границы предназначены для демонстрационных целей.

dave mankoff 13.12.2008 19:54

Хм, похоже, на самом деле не работает - столбцы не то, что я хотел. (Я хотел "col1 col2 col2 col2 col1 col1"; возможно, мне следовало выбрать менее запутанные имена, чтобы задать этот вопрос ...)

ShreevatsaR 13.12.2008 20:27

К сожалению, это не сработает, если коробки вообще различаются по высоте. Один из способов исправить это - поставить clear: right; на col2.

dave mankoff 13.12.2008 20:27

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

<table>
    <tr>
        <td>
            <p>One name</p> <textarea id = "one"></textarea>
        </td>
       <td>
            <p>XYZ name</p> <textarea id = "xyz"></textarea>
        </td>
    </tr>
   ....
 </table>

Выравнивание отлично работает со всеми браузерами.

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

dave mankoff 13.12.2008 20:36

Я не могу поместить его в (статическую) таблицу, потому что сами div генерируются динамически.

ShreevatsaR 16.12.2008 00:09

Таблицы - вполне приемлемое решение для этого ИМХО.

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

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

http://www.blueprintcss.org/ - отличный фреймворк ИМХО.

Может быть, вы можете использовать абсолютное позиционирование? Конечно, это зависит от остальной структуры вашей страницы, но часто это вполне жизнеспособно.

У вас есть Javascript - почему бы не использовать его?

Вы сказали это:

These divs are generated dynamically if the browser has Javascript, and I don't want to change the actual order that is displayed in the absence of Javascript, for semantic reasons...

Вы показываете эти <div> только в том случае, если у пользователя есть Javascript - почему бы не использовать Javascript для их перестановки?. Если вы переместите # 4 на место после # 5, это будет хорошо выглядеть с вашим текущим CSS.

Итак (с jQuery):

$("div:eq(3)").remove().insertAfter("div:eq(4)");

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

Думаю, это ваше решение (не проверено).

.left { width: 51%; float: left; }
.right { width: 49%; }

51% не позволяет им плавать рядом друг с другом, а затем просто позволяют всему контенту .right обернуться вокруг этих плавающих блоков.

Менее частое мышление дает больше с HTML / css, и опять же - НЕТ при использовании таблиц для макета.

=== [править] ===

Я провел тест на этом, и он действительно работает с парой настроек, И если вы знаете, что первый элемент плавает влево (или вправо, чтобы изменить поведение).

<style>
  div div { text-align: center; padding: 20px 0; overflow: hidden; }
  .left { width: 251px; float: left; background: red; }
  .right { width: 249px; background: green; }
</style>
<div style = "width: 500px;" >
  <div class = "left"> <p>1</p> </div>
  <div class = "right">  <p>2</p> </div>
  <div class = "left">  <p>3</p> </div>
  <div class = "left">  <p>4</p> </div>
  <div class = "right"> <p>5</p> </div>
  <div class = "right"> <p>6</p> </div>
</div>

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

Steve Perks 16.12.2008 18:33

Это дает: 1 2 <br/> 3 5 <br/> 4 6, НЕ 2 1 <br/> 3 5 <br/> 4 6. Я думаю, вам действительно нужно как-то изменить порядок элементов.

Nathan Long 16.12.2008 18:43

@ Натан - работает. Условие здесь заключается в том, что первый элемент должен плавать и быть шире, чем элемент упаковки. Я бы сказал, что если можно определить, в каком направлении должен плавать первый элемент, это вполне выполнимо. Я выставлю еще одно предложение, включающее это и jQuery.

Steve Perks 16.12.2008 18:52

@Steve - ваш подход кажется умным, но я точно скопировал ваш код и вижу # 1 слева от # 2. Как их изменить в CSS? Я думал, что более поздний элемент не может плавать выше, чем более ранний.

Nathan Long 16.12.2008 19:17

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

Steve Perks 16.12.2008 19:25

Отклоняюсь от этого вопроса. Это не выход. Объяснение в моем ответе

Steve Perks 16.12.2008 20:38

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

Nathan Long 18.12.2008 01:12

Вы не хотите использовать JavaScript? Если нет, и мой Wi-Fi работает, я посмотрю, смогу ли я выбить что-нибудь, что сделает это довольно быстро за вас.

Steve Perks 18.12.2008 01:20

Я чувствовал себя виноватым, что чистый метод css не работал, но если вы не против использовать JavaScript, чтобы получить то, что вам нужно, то вот какой-то jQuery, который будет работать (кто-то другой, вероятно, сможет очистить это для вы, если вам не нравится раздувание).

<style>
  #container { width: 500px; border: 1px grey solid; overflow: hidden; }
  #container .rightSide { width: 250px; float: right; }
  #container .left { width: 250px; background: red; padding: 20px 0; overflow: hidden; text-align: center; }
  #container .right { width: 250px; background: green; padding: 20px 0; overflow: hidden; text-align: center; }
</style>
<script type = "text/javascript">
$(document).ready(function() {
  $('#container').prepend('<div class = "rightSide"></div>');
  $('#container div.right').each(function() {
    var $rightContent = $(this).remove().html();
    $('.rightSide').append('<div class = "right">' + $rightContent + '</div>');
  });
});
</script>
<div id = "container" >
  <div class = "right"> <p>1</p> </div>
  <div class = "left">  <p>2</p> </div>
  <div class = "left">  <p>3</p> </div>
  <div class = "left">  <p>4</p> </div>
  <div class = "right"> <p>5</p> </div>
  <div class = "right"> <p>6</p> </div>
</div>

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

Steve Perks 21.01.2009 16:32

Решение 1

Если вы можете позволить себе дублировать HTML:

.left-column .right, .right-column .left {
    display: none;
}

Решение 2

Подождите немного, пока браузеры не поддержат CSS3:

.right {
    position: flow(side); 
}

Решение 3

Если ваши div имеют одинаковую высоту, используйте косвенный комбинатор смежных братьев и сестер. Несмотря на то, что он принадлежит к уровню CSS 3, это уже хорошо поддерживается:

.container {
    position: relative;
}

.left, .right {
    position: absolute;
    top : 0;
    width: 50%;
} 

.left {
    left: 0;
}

.right {
    left: 50%;
}

.left ~ .left, .right ~ .right {
    top : 100px;
}

.left ~ .left ~ .left, .right ~ .right ~ .right {
    top : 200px;
}

.left ~ .left ~ .left ~ .left, .right ~ .right ~ .right ~ .right {
    top : 300px;
}

... /* you need to include as many rules as the maximum possible height */

Проверьте 960 Сетка. Я использовал это в проектах в прошлом, и я должен сказать, что он работает довольно хорошо. Мало того, он прост в использовании и совместим во всех браузерах: D

Используя эту структуру:

<html>
    <head>
        <link rel = "stylesheet" type = "text/css" media = "all" href = "css/reset.css" />
        <link rel = "stylesheet" type = "text/css" media = "all" href = "css/text.css" />
        <link rel = "stylesheet" type = "text/css" media = "all" href = "css/960.css" />
     </head>
     <body>
     <div class = "container_16">
         <div class = "grid_1 alpha" style = "text-align:center;">
            2
         </div>
         <div class = "grid_1 omega" style = "text-align:center;">
            1
         </div>
         <div class = "clear"></div>
         <div class = "grid_1 alpha" style = "text-align:center;">
            4
         </div>
         <div class = "grid_1 omega" style = "text-align:center;">
            3
         </div>
         <div class = "clear"></div>
         <div class = "grid_1 alpha" style = "text-align:center;">
            5
         </div>
         <div class = "grid_1 omega" style = "text-align:center;">
            4
         </div>
    </div>
</body>
</html>

альтернативный текст http://img40.imageshack.us/img40/6889/cd3cc920a04b80e06b8efef.png

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

Другие вопросы по теме