CSS: две колонки

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

У меня есть куча divs, как это:

<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

(без "ясно", это беспечно производит

2 1
3 4
6 5

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

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

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

13.12.2008 16:12:48
11 ОТВЕТОВ

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

0
13.12.2008 16:28:00
Нет, он не работает без «чистых» ключей - он производит что-то совсем другое.
ShreevatsaR 13.12.2008 17:08:53

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

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

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

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

РЕДАКТИРОВАТЬ: я сказал в комментариях, что я не ожидаю, что CSS3 будет поддерживать такую ​​функцию, потому что она нарушает разделение контента и макета. Позже я вспомнил, что CSS3 планирует иметь сноски . Таким образом, если вы пометите некоторые из ваших div'ов с помощью «float: note», выбранные div-ы попадут в отдельную область «сноски» на странице. Я думаю, вы можете разместить их справа от остальной части макета.

2
13.12.2008 22:24:24
Хорошее описание моей проблемы, спасибо. В CSS3 что-то есть?
ShreevatsaR 13.12.2008 17:29:17
В css (не только css3) вы можете делать такие вещи, как «display: table-cell;» Это даст вам именно то, что вы хотите.
dave mankoff 13.12.2008 17:32:53
Не так далеко, как я знаю. Можно утверждать, что то, что вы хотите, изменяет структуру / содержание документа и, таким образом, находится за пределами мандата CSS, который должен только изменять представление.
buti-oxa 13.12.2008 17:35:00

В 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>

3
1.03.2018 11:33:04
Спасибо. (И да, я опущу "div" из названий классов :)) Так что же такое "198px", потому что это "400px / 2 - 1px"? И можно ли заставить его занимать всю ширину страницы вместо 400 пикселей?
ShreevatsaR 13.12.2008 16:46:29
да, он только поставил границы, чтобы показать вам макет (я думаю), поэтому, если вы установите рамку: 0px, вы можете получить 400px
inspite 13.12.2008 16:52:31
Ага. Границы для демонстрационных целей.
dave mankoff 13.12.2008 16:54:59
Хм, похоже, на самом деле не работает - столбцы не то, что я хотел. (Я хотел «col1 col2 col2 col2 col1 col1»; возможно, я должен был выбрать менее запутанные имена, чтобы задать этот вопрос ...)
ShreevatsaR 13.12.2008 17:27:18
Это не сработает, если ящики изменятся по высоте, к сожалению. Один из способов исправить это может быть ясно: правильно; на col2.
dave mankoff 13.12.2008 17:27:23

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

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

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

1
13.12.2008 17:29:12
Я думаю, что он хочет сохранить структуру div по семантическим причинам. Однако макеты таблиц все еще возможны - вы можете использовать свойство display для преобразования элементов в таблицы, строки таблицы и ячейки таблицы, по крайней мере, визуально. Никакой поддержки IE, однако :(
dave mankoff 13.12.2008 17:36:05
Я не могу поместить его в (статическую) таблицу, потому что сами div генерируются динамически.
ShreevatsaR 15.12.2008 21:09:41

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

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

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

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

0
13.12.2008 17:38:20

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

0
13.12.2008 22:27:31

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

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

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

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

Итак (с помощью jQuery):

$("div:eq(3)").remove().insertAfter("div:eq(4)");
1
16.12.2008 16:12:17

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

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

.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>
2
16.12.2008 18:03:39
Я работаю с парой изменений и предварительным условием, которое вы, возможно, сможете обойти в случае необходимости. Я отредактировал мой ответ с кодом там.
Steve Perks 16.12.2008 15:33:30
В результате получается: 1 2 <br/> 3 5 <br/> 4 6, НЕ 2 1 <br/> 3 5 <br/> 4 6. Я думаю, вам действительно нужно как-то изменить порядок элементов.
Nathan Long 16.12.2008 15:43:36
@ Натан - это работает. Условие здесь состоит в том, что первый элемент должен плавать И быть шире, чем упаковочный элемент. Я бы сказал, что если возможно определить, каким образом должен плавать первый элемент, это вполне выполнимо. Я выставлю еще одно предложение, включающее это и jQuery
Steve Perks 16.12.2008 15:52:06
@ Steve - ваш подход кажется умным, но я точно скопировал ваш код и вижу № 1 слева от № 2. Как CSS может изменить их порядок? Я думал, что более поздний элемент не может плавать выше, чем более ранний.
Nathan Long 16.12.2008 16:17:16
последний элемент не плавает, хотя. когда вы плаваете 2 предмета, 3-й незакрепленный предмет будет просто лежать в предоставленном месте. Я переключил содержимое, но только для того, чтобы подтвердить, что первый элемент должен быть плавающим.
Steve Perks 16.12.2008 16:25:08

Я чувствовал себя виноватым, что метод чистого 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>
0
10.12.2011 00:22:36
Мне так не нравятся отрицательные голоса без объяснения того, почему они находят информацию неверной. Интересно, как за это решение, которое является более правильным, проголосовали, где моя неудачная попытка использовать только css набирает голоса.
Steve Perks 21.01.2009 13:32:48

Решение 1

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

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

Решение 2

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

.right {
    position: flow(side); 
}

Решение 3

Если ваши дивы имеют одинаковую высоту, используйте косвенный соседний комбинатор . Несмотря на то, что он относится к уровню 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 */
2
10.06.2009 18:24:31

Проверьте 960 Grid System . Я использовал это на проектах в прошлом, и я должен сказать, что это работает довольно хорошо. Мало того, он прост в использовании и совместим во всех браузерах: 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 или макета.

0
10.06.2009 18:51:33