CSS верстка макета - PullRequest
4 голосов
/ 16 мая 2010

Среди множества двух (или трех) методик разметки столбцов Я иногда использую следующий:

<div class="left1">
  <div class="left2">
    left main content
  </div>
</div>
<div class="right1">
  <div class="right2">
    right sidebar
  </div>
</div>

вместе с:

.variant1 .left1 {
  float: left;
  margin-right: -200px;
  width: 100%;
}
.variant1 .left1 .left2 {
  margin-right: 200px;
}
.variant1 .right1 {
  float: right;
  width: 200px;
}

Это работает во всех основных браузерах. Но по какой-то очень странной причине точно такая же техника, но обратная не работает :

.variant2 .left1 {
  float: left;
  width: 200px;
}
.variant2 .right1 {
  float: right;
  margin-left: -200px;
  width: 100%;
}
.variant2 .right1 .right2 {
  margin-left: 200px;
}

Во втором варианте нельзя выбрать весь текст на боковой панели и невозможно щелкнуть все ссылки Это как минимум верно для Firefox и Chrome. В IE7 по крайней мере можно нажимать на ссылки, и Opera выглядит вполне нормально.

Кто-нибудь знает причину этого странного поведения? Это ошибка браузера?

Обратите внимание: я не ищу рабочую технику CSS с двумя колонками, я знаю, что их много. И мне не обязательно нужна эта техника для работы. Мне только нравится понимать причину, по которой второй вариант ведет себя так, как он.

Вот ссылка на небольшую тестовую страницу, которая должна проиллюстрировать проблему: http://selfthinker.org/stuff/css_layout_mystery.html

1 Ответ

1 голос
/ 16 мая 2010

Это базовая проблема со слоями. Давайте разберем спецификацию CSS на визуальном форматировании , чтобы выяснить, почему.

Порядок, в котором дерево рендеринга нарисовано на холсте, описывается в терминах стековых контекстов.

Хорошо, давайте посмотрим, в каком «стековом контексте» мы находимся. Для этого нам нужно знать, когда создается новый стековый контекст.

[Значение z-index для целого числа] ... - это уровень стека сгенерированного блока в текущем контексте стека. Блок также устанавливает локальный контекст стека, в котором его уровень стека равен «0».

Ну, у нас нет значений z-index - так что все они автоматически.

Корневой элемент формирует корневой контекст стека. Другие контексты суммирования генерируются любым позиционированным элементом (включая относительно позиционированные элементы), имеющим вычисленное значение «z-index», кроме «auto».

Нет, позиционированных элементов тоже нет. Похоже, мы все в «контексте укладки корня».

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

Это, безусловно, объясняет, почему .right1 закрашивает .left1 - это после него в исходном порядке. (Обратите внимание, что проблема с закрашиванием будет лучше, если вы удалите margin-left: 200px из .right2).

Итак, теперь, когда мы знаем проблему (и что она соответствует спецификации) - как мы можем это исправить? Проще всего было бы сделать z-индекс .left1 выше .right1. Поскольку они находятся в одном и том же контексте стека, более высокий z-индекс переопределит исходный порядок:

.variant2 .left1 { position: relative; z-index: 1; }

Или, если мы продолжим читать спецификацию - мы заметим, что:

Каждый контекст стека состоит из следующих уровней стека (от спины к фронту):

  • фон и границы элемента, формирующего контекст стека.
  • контексты суммирования потомков с отрицательными уровнями стека.
  • уровень стека, содержащий непозиционируемых потомков в потоке, не расположенных на уровне строки.
  • уровень суммирования для непозиционированных поплавков и их содержимого.
  • уровень стека для непозиционированных потомков in-level in-flow.
  • уровень стека для позиционируемых потомков с z-index: auto и любой контекст стека потомков с z-index: 0.
  • контексты укладки потомков с положительными уровнями стека.

, что означает, что мы можем просто сделать:

.variant2 .left1 { position: relative; }

, который даст .left1 "уровень суммирования" 6 - который переопределит .right1 уровень стека 4.

...