Введение в стандарты Web

Абсолютное и фиксированное позиционирование CSS

Разбить на страницы
Показывать лекцию целиком

Введение

Теперь пришло время обратить наше внимание на вторую пару значений свойства position - absolute и fixed. Первая пара значений - static и relative - тесно связаны, и мы рассмотрели их достаточно подробно в предыдущей статье.

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

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

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

Статья имеет следующую структуру:

Объемлющие блоки 
Абсолютное позиционирование 
	Определение позиции 
	Определение размеров 
	Третье измерение - z-индекс 
		Локальные контексты стеков 
Фиксированное позиционирование 
Заключение 
Контрольные вопросы

Прежде чем говорить обо всем этом, рассмотрим важную предварительную концепцию - объемлющие блоки.

Объемлющие блоки

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

Для статических боксов и относительно позиционированных боксов объемлющий блок является ближайшим предком блочного уровня - элемент предок, другими словами. Для абсолютно позиционированных элементов, однако это немного сложнее. В этом случае объемлющий блок является ближайшим позиционированным предком. Под "позиционированным" понимается элемент, свойство position которого задано как relative, absolute или fixed - иными словами, любой элемент, кроме обычных статических элементов.

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

Если абсолютно позиционированный элемент не имеет позиционированного предка, то объемлющий блок называют иногда "начальным объемлющим блоком", что на практике совпадает с элементом html. При просмотре Web-страницы на экране это означает окно браузера, при печати страницы это означает границу страницы.

Элементы с фиксированным позиционированием слегка от этого отличаются -- они всегда имеют начальный объемлющий блок в качестве своего объемлющего блока.

Итак, давайте суммируем это в множестве простых шагов - чтобы найти объемлющий блок для элемента с position:absolute, необходимо сделать следующее:

  • Посмотрите на элемент предок абсолютно позиционированного элемента - имеет ли свойство position этого элемента одно из значений relative, absolute или fixed?
  • Если это так, то вы нашли объемлющий блок.
  • Если нет, перейдите в элемент предок элемента предка и повторите с шага 1, пока не найдете объемлющий блок или закончатся элементы предки.
  • Если вы дошли до элемента html, не найдя размещенного предка, то объемлющим элементом будет элемент html.
  • Абсолютное позиционирование

    Фиксированное позиционирование является специальной формой абсолютного позиционирования, поэтому мы рассмотрим его позже, и сосредоточимся здесь на более общем случае. Если не сказано другое, то при использовании термина "абсолютное позиционирование" с данного момента и до конца статьи будут подразумеваться элементы, имеющие position:fixed или position:absolute.

    Определение позиции

    При рассмотрении относительного позиционирования мы узнали, что для определения позиции бокса можно использовать свойства top, right, bottom и left. Эти же свойства используются для определения позиции абсолютно позиционированного бокса, но способ их использования совершенно другой.

    Для относительно позиционированного элемента четыре свойства определяют относительное расстояние для смещения сгенерированного бокса. Помните, что в случае относительного позиционирования они дополняют друг друга, так что top:1em и bottom:-1em означают одно и то же, и не имеет смысла определять одновременно top и bottom (или left и right ) для одного и того же элемента, так как одно из значений будет проигнорировано.

    Эти положения неверны в случае абсолютного позиционирования. Здесь все четыре свойства можно использовать одновременно для определения расстояния от каждого края позиционированного элемента до соответствующего края объемлющего блока. Можно определить также позицию одного из углов абсолютно позиционированного бокса - например, используя top и left - а затем определить размеры бокса, используя width и height (или вообще не использовать width и height, если вы хотите позволить боксу сжиматься в соответствии с его контентом).

    Microsoft Internet Explorer версии 6 и более старые не поддерживают метод задания всех четырех ребер, но поддерживают метод задания одного угла и размеров.

    /* Этот метод работает в IE6 */
    #foo {
      position: absolute;
      top: 3em;
      left: 0;
      width: 30em;
      height: 20em;
    }
    
    /* Этот метод не работает в IE6 */
    #foo {
      position: absolute;
      top: 3em;
      right: 0;
      bottom: 3em;
      left: 0;
    }

    Необходимо здесь запомнить, что значения, которые задаются для свойств top, right, bottom и left определяют расстояние от краев элемента до соответствующих краев его объемлющего блока. Это не соответствует координатной системе, где каждое значение задается относительно одной точки начала координат. Например, right:2em означает, что правый край абсолютно позиционированного бокса будет отстоять на 2em от правого края объемлющего блока.

    Поэтому при использовании абсолютного позиционирования критически важно знать, что является объемлющим блоком. Именно поэтому задание position:relative на объемлющем блоке будет так полезно, даже если вы не сдвигаете позицию бокса. Это позволяет сделать элемент объемлющим блоком для его абсолютно позиционированных потомков, что обеспечивает управление.

    Давайте рассмотрим пример, чтобы увидеть, как это работает.

    1. Скопируйте представленный ниже код в текстовый редактор и сохраните документ как absolute.html.

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Absolute Positioning</title>
        <link rel="stylesheet" type="text/css" href="absolute.css">
      </head>
      <body>
        <div id="outer">
          <div id="inner"></div>
        </div>
      </body>
    </html>

    2. Затем скопируйте следующий код в новый файл и сохраните его как absolute.css.

    html, body {
      margin: 0;
      padding: 0;
    }
    
    #outer {
      margin: 5em;
      border: 1px solid #f00;
    }
    
    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
    }

    3. Сохраните оба файла и загрузите документ HTML в браузер. Вы увидите серый прямоугольник, окруженный достаточно широкой красной границей. Элемент #inner имеет указанную ширину и высоту и серый цвет фона. Элемент #outer, который является структурным предком #inner, имеет красную границу. Он имеет со всех сторон также поле шириной 5em, чтобы сместить его от краев окна браузера, и более четко видеть, что происходит. Пока ничего удивительного, не так ли? Высота элемента #outer задана его элементом потомком ( #inner ) и шириной горизонтальных полей.

    4. Теперь посмотрим, что произойдет, если сделать элемент #inner абсолютно позиционированным! Добавьте следующее выделенное объявление в правило #inner:

    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
      position: absolute;
    }

    5. Сохраните и перезагрузите документ. Вместо красной границы вокруг серого прямоугольника, теперь имеется только что-то похожее на более толстую верхнюю границу. А серый бокс вообще не сдвинулся! Вы ожидали это?

    Здесь произошли два интересных события. Прежде всего, при абсолютном позиционировании элемент #inner полностью удаляется из потока документа. Это означает, что его предок, #outer, теперь не имеет потомков в нормальном потоке документа, так что его высота схлопывается до нуля.

    То, что выглядит как красная линия толщиной 2px, является в действительности границей толщиной 1px вокруг элемента с нулевой высотой - вы видите верхнюю и нижнюю границы и ничего между ними.

    Второе интересное событие состоит в том, что абсолютно позиционированный бокс не смещается. Значение по умолчанию для свойств top, right, bottom и left будет auto, что означает, что абсолютно позиционированный бокс появится точно там, где он был бы, если бы не был позиционирован. Однако так как он был удален из потока, он будет перекрывать все элементы в нормальном потоке, которые следуют за ним.

    На самом деле это очень полезно - можно использовать это, если вы хотите только переместить сгенерированный бокс в одном направлении. Например, в раскрывающемся меню, управляемом CSS, "раскрывающиеся" панели можно абсолютно позиционировать, определяя только свойство top. Они будут затем автоматически появляться в ожидаемой координате по оси X (также, как и их предок).

    6. Затем давайте зададим высоту для элемента #outer, чтобы он снова выглядел как прямоугольник, и смещал #inner в сторону. Добавьте следующие выделенные строки в правила CSS:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
    }
    
    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    7. Сохраните и перезагрузите, и вы увидите некоторые изменения. Элемент #outer будет теперь снова прямоугольником, так как вы задали для него высоту. Элемент #inner смещается в сторону, но не туда, куда вы могли бы ожидать. Он находится на расстоянии 1em не от левой границы своего предка, а на расстоянии 1em от левого края окна!

    Причина в том, как объяснялось выше, что элемент #inner не имеет позиционированного предка, поэтому его объемлющий блок является начальным объемлющим блоком. Если определить позицию отличную от auto, то она будет задана относительно соответствующего края объемлющего блока. Если задать left:1em, то левый край элемента #inner закончится на расстоянии 1em от левого края окна.

    8. Если вы хотите вместо этого, чтобы он был на расстоянии 1em от левого края его элемента предка, то необходимо сделать предка объемлющим блоком. Для этого мы используем теперь прием, который упоминался ранее в статье - сделаем блок предок относительно позиционированным. Добавьте следующую выделенную строку в правило #outer:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
      position: relative;
    }

    9. Сохраните и перезагрузите документ - и вот! Серый прямоугольник теперь находится на расстоянии 1em от левой границы элемента предка. Задание position:relative в правиле #outer делает его позиционированным и задает как объемлющий блок для всех абсолютно позиционированных потомков, которые он мог бы иметь. Задание left:1em для элемента #inner теперь отсчитывается от левого края элемента #outer, а не от левого края окна браузера.

    Определение размеров

    Абсолютно позиционированные элементы будут сжиматься, чтобы соответствовать своему контенту, если не определить их размеры. Ширину можно определить, задавая свойства left и right, или задавая свойство width. Высоту можно определить, задавая свойства top и bottom, или задавая свойство height.

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

    Для любого абсолютно позиционированного элемента значения процентов для свойств left, right и width определяются относительно ширины объемлющего блока. Значения процентов для свойств top, bottom и height определяются относительно высоты объемлющего блока.

    Internet Explorer 6 и более старые версии, а также Opera 8 и более старые версии, воспринимают это совершенно неправильно и используют вместо этого размеры блока предка. Давайте поэкспериментируем с другим примером, чтобы увидеть, что это может иметь большое значение.

    Начнем с определения размеров элемента #inner, используя значения процентов - сделайте следующие изменения в правиле #inner:

    #inner {
      width: 50%;
      height: 50%;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    Сохраните и перезагрузите и вы увидите, что серый прямоугольник станет шире и ниже (по крайней мере, если вы используете современный браузер). Объемлющий блок по-прежнему будет #outer, так как он имеет position:relative. Ширина элемента #inner составляет сейчас половину #outer, а его высота половину высоты #outer.

    Давайте сделаем окно просмотра снова объемлющим блоком, чтобы увидеть разницу! Сделайте следующие изменения в #outer:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
      position: static;
    }

    Сохраните и перезагрузите документ - видите разницу? Серый бокс теперь имеет половину ширины и половину высоты окна браузера.

    Как можно видеть, знание объемлющих блоков абсолютно важно!

    Третье измерение - z-индекс

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

    Двумя основными осями на Web-странице являются горизонтальная ось X и вертикальная ось Y. Начало координатной системы находится в верхнем левом углу окна просмотра, т.е. в этом месте оба значения X и Y равны 0.

    Но существует также ось Z, которую можно вообразить направленной перпендикулярно к поверхности монитора (или бумаги при печати). Большие значения Z указывают позицию "перед" меньшими значениями Z. Значения Z могут быть также отрицательными, что указывает на положение "позади" некоторой точки привязки (я сейчас объясню, что это за точка привязки).

    Прежде чем продолжить, я должен предупредить, что это одна из самых сложных тем в CSS, поэтому не падайте духом, если вы что-то не поймете при первом чтении.

    Позиционированные элементы (включая относительно позиционированные элементы), изображаются в так называемом контексте стека. Элементы в контексте стека имеют одну точку привязки на оси Z. Подробнее об этом ниже. Можно изменить позицию Z (называемую также уровнем стека) позиционированного элемента с помощью свойства z-index. Это значение может быть целым числом (которое может быть отрицательным) или одним из ключевых слов auto или inherit. Значением по умолчанию является auto, которое означает, что элемент имеет такой же уровень стека, как и его предок.

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

    Если Z-индекс определяется как положительное целое число, то вы присваиваете ему уровень стека "перед" другими элементами в том же контексте стека, которые имеют меньший уровень стека. Z-индекс равный 0 (ноль) означает то же самое, что и auto, но имеется отличие, к которому я скоро вернусь. Отрицательное целое значение Z-индекса присваивает уровень стека "позади" уровня стека предка.

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

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

  • Фон и границы элементов, которые формируют контекст стека
  • Позиционированные потомки с отрицательными уровнями стека
  • Потомки блочного уровня в нормальном потоке
  • Плавающие потомки
  • Потомки строкового уровня в нормальном потоке
  • Позиционированные потомки с уровнем стека, заданным как auto или 0 (ноль)
  • Позиционированные потомки с положительными уровнями стека
  • Выделенные позиции являются элементами, уровень стека которых можно изменять с помощью свойства z-index.

    Все это может быть достаточно сложно вообразить, поэтому давайте сделаем несколько практических экспериментов для иллюстрации Z-индекса. 1. Начнем с добавления следующей выделенной строки в пример документа:

    <body>
      <div id="outer">
        <div id="inner"></div>
        <div id="second"></div>
      </div>
    </body>

    2. Затем необходимо восстановить код CSS, так чтобы #outer был охватывающим блоком, и задать непроцентные размеры для #inner. Давайте сделаем также #outer немного выше, чтобы было больше пространства для эксперимента. Сделайте в правилах следующие выделенные изменения:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 8em;
      position: relative;
    }
    
    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    3. Добавьте также правило для элемента #second:

    #second {
      width: 5em;
      height: 5em;
      background-color: #00f;
      position: absolute;
      top: 1em;
      left: 2em;
    }

    4. Сохраните и перезагрузите документ, и вы увидите ярко синий бокс перекрывающий серый бокс. Оба бокса имеют один уровень стека ( auto, начальное значение, которое означает уровень стека 0), но синий бокс изображается перед серым боксом, так как он появляется позже в исходном коде. Можно сделать так, чтобы первый бокс выводился сверху, задавая для него положительный уровень стека. Необходимо задать его просто больше 0 - нет никакой необходимости использовать такие значения как 10000. Добавьте следующую выделенную строку в правило #inner:

    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: absolute;
      left: 1em;
      z-index: 1;
    }

    5. Сохраните и перезагрузите, и теперь вы увидите, что серый бокс выводится сверху синего.

    Локальные контексты стеков

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

    Каждый элемент, z-индекс которого определен как целое число, создает новый, "локальный", контекст стека, в котором сам элемент имеет уровень стека 0. В этом состоит различие, о котором говорилось ранее между z-index: auto и z-index: 0. Первый из них не создает новый контекст стека, а второй создает.

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

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

    Локальный контекст стека аналогичен такому конверту. Он содержит связанные элементы вместе и не позволяет другим элементам появится между ними. Можно отсортировать контент в каждом конверте требуемым образом, но этот порядок сортировки применяется только в этом конверте, и не распространяется на стек бумаг в целом. Стек содержит теперь смесь несвязанных бумаг (элементов с уровнем стека auto ), и конвертов (элементов с целочисленным уровнем стека). Конверты с положительными уровнями стека лежат поверх несвязанных бумаг, в то время как конверты с отрицательными уровнями стека окажутся внизу пачки.

    Каждый раз, когда целое значение присваивается свойству z-index элемента, создается "конверт", который содержит этот элемент и его потомков.

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

    1. Начнем с добавления некоторого контента в два внутренних элемента - добавьте выделенные строки в документ HTML:

    <div id="inner">
      <span></span>
    </div>
    <div id="second">
      <span></span>
    </div>

    2. Добавьте правило CSS, которое будет применяться к обоим этим элементам span:

    span {
      position: absolute;
      top: 2em;
      left: 2em;
      width: 3em;
      height: 3em;
    }

    Оно делает элементы span абсолютно позиционированными и задает их позиции и размеры. Хотя подождите секунду - элементы span являются строковыми - как можно определить размеры для строковых элементов? Ответ состоит в том, что абсолютно позиционированные элементы, подобно плавающим элементам, автоматически генерируют блочные боксы.

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

    3. Давайте теперь добавим немного цвета в элементы span, чтобы можно было видеть, где они появляются. Добавьте следующие правила в таблицу стилей:

    #inner span {
      background-color: #ff0;
    }
    
    #second span {
      background-color: #0ff;
    }

    4. Сохраните и перезагрузите документ, и вы должны увидеть желтый квадрат в нижнем правом углу большего по размеру серого квадрата, и голубой квадрат в нижнем правом углу большего по размеру синего квадрата. Серый и желтый квадраты появятся перед синим и голубым квадратами, так как серый квадрат имеет z-index:1.

    5. Что если нам нужно, чтобы голубой квадрат был перед всеми другими квадратами? Для этого нужно только задать для него более высокий уровень стека, чем у серого квадрата. В действительности достаточно задать ему такой же уровень стека, как и у серого квадрата, так как голубой квадрат появляется в разметке позже. Давайте проверим это - сделайте следующее изменение в коде CSS:

    #second span {
      background-color: #0ff;
      z-index: 1;
    }

    6. Сохраните и перезагрузите документ. Если используемый браузер правильно поддерживает рекомендацию CSS, то голубой квадрат должен теперь быть впереди.

    Серый квадрат имеет свойство z-index:1, что означает, что он создает локальный контекст стека. Другими словами, вы создали один из таких "конвертов" и поместили внутрь серый квадрат и его желтый квадрат потомков.

    Запутались? Следующий эксперимент должен сделать все понятнее.

    1. Задайте большой уровень стека для желтого квадрата, чтобы вывести его вперед -- сделайте следующие изменения в коде CSS:

    #inner span {
      background-color: #ff0;
      z-index: 4;
    }

    2. Если сохранить и перезагрузить документ, вы увидите … вообще никаких изменений! Уровень стека, который был определен для желтого квадрата, применяется в локальном контексте стека, созданном серым квадратом - желтый квадрат находится в конверте вместе со своим серым предком. Можно было бы переместить голубой квадрат вперед, так как его предок (синий квадрат) не создает локальный контекст стека - он имеет неявно подразумеваемое свойство z-index:auto. Синий квадрат является свободным документом в стеке. Желтый и голубой квадраты находятся в действительности в небольших конвертах сами по себе (они имеют целочисленный уровень стека и создают свои собственные локальные контексты стеков)

    3. Если синий квадрат создает локальный контекст стека, вы не сможете переместить голубой квадрат вперед, если не переместите также вперед его предка (синий квадрат). Давайте попробуем это сделать - сделайте следующие изменения в коде CSS:

    #inner {
      
      ...
      
      z-index: 2;
    }
    
    #second {
      
      ...
      
      z-index: 1;
    }
    
    #second span {
      
      ...
      
      z-index: 3;
    }

    4. Сохраните и перезагрузите. Теперь серый квадрат и синий квадрат создают локальные контексты стеков, предоставляя нам два конверта. Внизу стека находится конверт с уровнем стека 1, содержащий два внутренних конверта (синий квадрат и голубой квадрат). Вверху стека находится конверт с уровнем стека 2, содержащий два внутренних конверта (серый квадрат и желтый квадрат). В первом конверте синий квадрат имеет локальный уровень стека 0, и поэтому появляется позади голубого квадрата, который имеет локальный уровень стека 3. Во втором конверте серый квадрат имеет локальный уровень стека 0, и поэтому появится позади желтого квадрата с локальным уровнем стека 4. рис 37.1 показывает четыре бокса и два контекста локального стека по сторонам, вдоль оси Z.(рис 37.1) Иллюстрация различных контекстов стеков. Элементы, появляющиеся внутри "2" всегда будут появляться перед всеми элементами внутри "1". Затем внутри каждого контекста стека элементы с большим значением z-index появятся перед элементами с меньшим значением z-index. Если два элемента имеют одинаковое значение z-index, то элемент, который появляется в разметке позже будет находиться впереди

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

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

    Фиксированное позиционирование

    Элемент с заданным свойством position:fixed фиксируется относительно области просмотра. Он остается там, где есть, даже если документ прокручивается. Для media="print" фиксированный элемент будет повторяться на каждой печатной странице.

    Отметим, что Internet Explorer версии 6 и более старых версий вообще не поддерживает фиксированное позиционирование. При использовании одного из этих браузеров вы не сможете увидеть результаты примеров из этого раздела.

    В то время как позиция и размеры элемента с position:absolute определяются относительно его объемлющего блока, позиция и размеры элемента с position:fixed всегда определяются относительно начального объемлющего блока. Это обычно будет область просмотра: окно браузера или бокс страницы бумаги.

    Чтобы продемонстрировать это, в примере ниже мы сделаем один из элементов фиксированным. Другой элемент сделаем очень высоким, чтобы вызвать появление полосы прокрутки, чтобы можно было легче увидеть создаваемый результат.

    1. Сделайте следующие изменения в коде CSS:

    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: fixed;
      top: 1em;
      left: 1em;
    }
    
    #second {
      width: 5em;
      height: 150em;
      background-color: #00f;
      position: absolute;
      top: 1em;
      left: 2em;
    }

    2. Сохраните и перезагрузите документ. Если вертикальная полоса прокрутки не появится, увеличьте значение height для #second. (Какой, однако, должен быть огромный монитор?)

    Высокий синий элемент расширяется ниже окна. Прокрутите страницу вниз, и удерживайте взгляд на сером квадрате в верхнем левом углу. #inner теперь зафиксирован в позиции 1em от верха окна и 1em от левой стороны, поэтому при прокрутке серый бокс остается в одном и том же месте на экране.

    Заключение

    Абсолютно позиционированные элементы полностью удаляются из потока документа. Они будут перекрывать другой контент, если не выделить для них пространство. Если все элементы потомки контейнера абсолютно позиционированы, высота предка будет схлопываться до нуля.

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

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

    Позиции каждого края абсолютно позиционированного элемента можно определить с помощью свойств top, right, bottom и left. Значение каждого свойства определяет расстояние от этого края до соответствующего края объемлющего блока элемента.

    Все позиционированные элементы изображаются на некотором уровне стека в контексте стека. Можно изменить уровень стека позиционированного элемента с помощью свойства z-index. Когда z-index определен как целочисленное значение, элемент создает локальный контекст стека для своих потомков.

    Контрольные вопросы

  • Отмените изменения в примере с фиксированным позиционированием и затем измените порядок стека четырех абсолютно позиционированных квадратов, так чтобы серый квадрат был внизу, а затем шли синий, желтый и голубой квадраты в данном порядке. (Совет: удалите все объявления z-index и начните сначала.)
  • Переместите желтый квадрат вверх и вправо, задавая top:-1em и left:8em. Затем сделайте так, чтобы он появился позади элемента #outer, чтобы красная граница пересекала желтый квадрат.
  • Повторите трех-столбцовую компоновку, созданную в статье о статическом и относительном позиционировании, используя вместо этого абсолютное позиционирование. Так как будет невозможно создать нижний колонтитул во всю ширину, можно удалить элемент #footer, но больше ничего изменять в разметке не разрешается (кроме ссылки на таблицу стилей).
  • Модифицируйте компоновку из предыдущего упражнения, чтобы навигация использовала фиксированное позиционирование. Нужно будет удалить автоматические горизонтальные поля на элементе body, чтобы это было возможно. Добавьте достаточно контента в основной столбец и/или боковую панель, чтобы появилась панель прокрутки, чтобы можно было проверить, что все работает.
  • Об авторе

    Томми Олссон является прагматичным пропагандистом стандартов Web и доступности, который живет в малонаселенной области центральной Швеции. Он написал свой первый документ HTML в 1993 г. и является в настоящее время техническим Web-мастером для правительственного агентства Швеции.

    Он написал пока одну книгу - Полный справочник по CSS (совместно с Полем О'Брайеном) - и поддерживает крайне нерегулярно блог с названием Кукушка-аутист (http://www.autisticcuckoo.net/).

    Материалы этого курса имеют лицензию Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
    Страницы:

    Введение

    Теперь пришло время обратить наше внимание на вторую пару значений свойства position - absolute и fixed. Первая пара значений - static и relative - тесно связаны, и мы рассмотрели их достаточно подробно в предыдущей статье.

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

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

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

    Статья имеет следующую структуру:

    Объемлющие блоки 
    Абсолютное позиционирование 
    	Определение позиции 
    	Определение размеров 
    	Третье измерение - z-индекс 
    		Локальные контексты стеков 
    Фиксированное позиционирование 
    Заключение 
    Контрольные вопросы

    Прежде чем говорить обо всем этом, рассмотрим важную предварительную концепцию - объемлющие блоки.

    Объемлющие блоки

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

    Для статических боксов и относительно позиционированных боксов объемлющий блок является ближайшим предком блочного уровня - элемент предок, другими словами. Для абсолютно позиционированных элементов, однако это немного сложнее. В этом случае объемлющий блок является ближайшим позиционированным предком. Под "позиционированным" понимается элемент, свойство position которого задано как relative, absolute или fixed - иными словами, любой элемент, кроме обычных статических элементов.

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

    Если абсолютно позиционированный элемент не имеет позиционированного предка, то объемлющий блок называют иногда "начальным объемлющим блоком", что на практике совпадает с элементом html. При просмотре Web-страницы на экране это означает окно браузера, при печати страницы это означает границу страницы.

    Элементы с фиксированным позиционированием слегка от этого отличаются -- они всегда имеют начальный объемлющий блок в качестве своего объемлющего блока.

    Итак, давайте суммируем это в множестве простых шагов - чтобы найти объемлющий блок для элемента с position:absolute, необходимо сделать следующее:

  • Посмотрите на элемент предок абсолютно позиционированного элемента - имеет ли свойство position этого элемента одно из значений relative, absolute или fixed?
  • Если это так, то вы нашли объемлющий блок.
  • Если нет, перейдите в элемент предок элемента предка и повторите с шага 1, пока не найдете объемлющий блок или закончатся элементы предки.
  • Если вы дошли до элемента html, не найдя размещенного предка, то объемлющим элементом будет элемент html.
  • Абсолютное позиционирование

    Фиксированное позиционирование является специальной формой абсолютного позиционирования, поэтому мы рассмотрим его позже, и сосредоточимся здесь на более общем случае. Если не сказано другое, то при использовании термина "абсолютное позиционирование" с данного момента и до конца статьи будут подразумеваться элементы, имеющие position:fixed или position:absolute.

    Определение позиции

    При рассмотрении относительного позиционирования мы узнали, что для определения позиции бокса можно использовать свойства top, right, bottom и left. Эти же свойства используются для определения позиции абсолютно позиционированного бокса, но способ их использования совершенно другой.

    Для относительно позиционированного элемента четыре свойства определяют относительное расстояние для смещения сгенерированного бокса. Помните, что в случае относительного позиционирования они дополняют друг друга, так что top:1em и bottom:-1em означают одно и то же, и не имеет смысла определять одновременно top и bottom (или left и right ) для одного и того же элемента, так как одно из значений будет проигнорировано.

    Эти положения неверны в случае абсолютного позиционирования. Здесь все четыре свойства можно использовать одновременно для определения расстояния от каждого края позиционированного элемента до соответствующего края объемлющего блока. Можно определить также позицию одного из углов абсолютно позиционированного бокса - например, используя top и left - а затем определить размеры бокса, используя width и height (или вообще не использовать width и height, если вы хотите позволить боксу сжиматься в соответствии с его контентом).

    Microsoft Internet Explorer версии 6 и более старые не поддерживают метод задания всех четырех ребер, но поддерживают метод задания одного угла и размеров.

    /* Этот метод работает в IE6 */
    #foo {
      position: absolute;
      top: 3em;
      left: 0;
      width: 30em;
      height: 20em;
    }
    
    /* Этот метод не работает в IE6 */
    #foo {
      position: absolute;
      top: 3em;
      right: 0;
      bottom: 3em;
      left: 0;
    }

    Необходимо здесь запомнить, что значения, которые задаются для свойств top, right, bottom и left определяют расстояние от краев элемента до соответствующих краев его объемлющего блока. Это не соответствует координатной системе, где каждое значение задается относительно одной точки начала координат. Например, right:2em означает, что правый край абсолютно позиционированного бокса будет отстоять на 2em от правого края объемлющего блока.

    Поэтому при использовании абсолютного позиционирования критически важно знать, что является объемлющим блоком. Именно поэтому задание position:relative на объемлющем блоке будет так полезно, даже если вы не сдвигаете позицию бокса. Это позволяет сделать элемент объемлющим блоком для его абсолютно позиционированных потомков, что обеспечивает управление.

    Давайте рассмотрим пример, чтобы увидеть, как это работает.

    1. Скопируйте представленный ниже код в текстовый редактор и сохраните документ как absolute.html.

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
    <html>
      <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Absolute Positioning</title>
        <link rel="stylesheet" type="text/css" href="absolute.css">
      </head>
      <body>
        <div id="outer">
          <div id="inner"></div>
        </div>
      </body>
    </html>

    2. Затем скопируйте следующий код в новый файл и сохраните его как absolute.css.

    html, body {
      margin: 0;
      padding: 0;
    }
    
    #outer {
      margin: 5em;
      border: 1px solid #f00;
    }
    
    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
    }

    3. Сохраните оба файла и загрузите документ HTML в браузер. Вы увидите серый прямоугольник, окруженный достаточно широкой красной границей. Элемент #inner имеет указанную ширину и высоту и серый цвет фона. Элемент #outer, который является структурным предком #inner, имеет красную границу. Он имеет со всех сторон также поле шириной 5em, чтобы сместить его от краев окна браузера, и более четко видеть, что происходит. Пока ничего удивительного, не так ли? Высота элемента #outer задана его элементом потомком ( #inner ) и шириной горизонтальных полей.

    4. Теперь посмотрим, что произойдет, если сделать элемент #inner абсолютно позиционированным! Добавьте следующее выделенное объявление в правило #inner:

    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
      position: absolute;
    }

    5. Сохраните и перезагрузите документ. Вместо красной границы вокруг серого прямоугольника, теперь имеется только что-то похожее на более толстую верхнюю границу. А серый бокс вообще не сдвинулся! Вы ожидали это?

    Здесь произошли два интересных события. Прежде всего, при абсолютном позиционировании элемент #inner полностью удаляется из потока документа. Это означает, что его предок, #outer, теперь не имеет потомков в нормальном потоке документа, так что его высота схлопывается до нуля.

    То, что выглядит как красная линия толщиной 2px, является в действительности границей толщиной 1px вокруг элемента с нулевой высотой - вы видите верхнюю и нижнюю границы и ничего между ними.

    Второе интересное событие состоит в том, что абсолютно позиционированный бокс не смещается. Значение по умолчанию для свойств top, right, bottom и left будет auto, что означает, что абсолютно позиционированный бокс появится точно там, где он был бы, если бы не был позиционирован. Однако так как он был удален из потока, он будет перекрывать все элементы в нормальном потоке, которые следуют за ним.

    На самом деле это очень полезно - можно использовать это, если вы хотите только переместить сгенерированный бокс в одном направлении. Например, в раскрывающемся меню, управляемом CSS, "раскрывающиеся" панели можно абсолютно позиционировать, определяя только свойство top. Они будут затем автоматически появляться в ожидаемой координате по оси X (также, как и их предок).

    6. Затем давайте зададим высоту для элемента #outer, чтобы он снова выглядел как прямоугольник, и смещал #inner в сторону. Добавьте следующие выделенные строки в правила CSS:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
    }
    
    #inner {
      width: 6em;
      height: 4em;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    7. Сохраните и перезагрузите, и вы увидите некоторые изменения. Элемент #outer будет теперь снова прямоугольником, так как вы задали для него высоту. Элемент #inner смещается в сторону, но не туда, куда вы могли бы ожидать. Он находится на расстоянии 1em не от левой границы своего предка, а на расстоянии 1em от левого края окна!

    Причина в том, как объяснялось выше, что элемент #inner не имеет позиционированного предка, поэтому его объемлющий блок является начальным объемлющим блоком. Если определить позицию отличную от auto, то она будет задана относительно соответствующего края объемлющего блока. Если задать left:1em, то левый край элемента #inner закончится на расстоянии 1em от левого края окна.

    8. Если вы хотите вместо этого, чтобы он был на расстоянии 1em от левого края его элемента предка, то необходимо сделать предка объемлющим блоком. Для этого мы используем теперь прием, который упоминался ранее в статье - сделаем блок предок относительно позиционированным. Добавьте следующую выделенную строку в правило #outer:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
      position: relative;
    }

    9. Сохраните и перезагрузите документ - и вот! Серый прямоугольник теперь находится на расстоянии 1em от левой границы элемента предка. Задание position:relative в правиле #outer делает его позиционированным и задает как объемлющий блок для всех абсолютно позиционированных потомков, которые он мог бы иметь. Задание left:1em для элемента #inner теперь отсчитывается от левого края элемента #outer, а не от левого края окна браузера.

    Определение размеров

    Абсолютно позиционированные элементы будут сжиматься, чтобы соответствовать своему контенту, если не определить их размеры. Ширину можно определить, задавая свойства left и right, или задавая свойство width. Высоту можно определить, задавая свойства top и bottom, или задавая свойство height.

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

    Для любого абсолютно позиционированного элемента значения процентов для свойств left, right и width определяются относительно ширины объемлющего блока. Значения процентов для свойств top, bottom и height определяются относительно высоты объемлющего блока.

    Internet Explorer 6 и более старые версии, а также Opera 8 и более старые версии, воспринимают это совершенно неправильно и используют вместо этого размеры блока предка. Давайте поэкспериментируем с другим примером, чтобы увидеть, что это может иметь большое значение.

    Начнем с определения размеров элемента #inner, используя значения процентов - сделайте следующие изменения в правиле #inner:

    #inner {
      width: 50%;
      height: 50%;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    Сохраните и перезагрузите и вы увидите, что серый прямоугольник станет шире и ниже (по крайней мере, если вы используете современный браузер). Объемлющий блок по-прежнему будет #outer, так как он имеет position:relative. Ширина элемента #inner составляет сейчас половину #outer, а его высота половину высоты #outer.

    Давайте сделаем окно просмотра снова объемлющим блоком, чтобы увидеть разницу! Сделайте следующие изменения в #outer:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 4em;
      position: static;
    }

    Сохраните и перезагрузите документ - видите разницу? Серый бокс теперь имеет половину ширины и половину высоты окна браузера.

    Как можно видеть, знание объемлющих блоков абсолютно важно!

    Третье измерение - z-индекс

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

    Двумя основными осями на Web-странице являются горизонтальная ось X и вертикальная ось Y. Начало координатной системы находится в верхнем левом углу окна просмотра, т.е. в этом месте оба значения X и Y равны 0.

    Но существует также ось Z, которую можно вообразить направленной перпендикулярно к поверхности монитора (или бумаги при печати). Большие значения Z указывают позицию "перед" меньшими значениями Z. Значения Z могут быть также отрицательными, что указывает на положение "позади" некоторой точки привязки (я сейчас объясню, что это за точка привязки).

    Прежде чем продолжить, я должен предупредить, что это одна из самых сложных тем в CSS, поэтому не падайте духом, если вы что-то не поймете при первом чтении.

    Позиционированные элементы (включая относительно позиционированные элементы), изображаются в так называемом контексте стека. Элементы в контексте стека имеют одну точку привязки на оси Z. Подробнее об этом ниже. Можно изменить позицию Z (называемую также уровнем стека) позиционированного элемента с помощью свойства z-index. Это значение может быть целым числом (которое может быть отрицательным) или одним из ключевых слов auto или inherit. Значением по умолчанию является auto, которое означает, что элемент имеет такой же уровень стека, как и его предок.

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

    Если Z-индекс определяется как положительное целое число, то вы присваиваете ему уровень стека "перед" другими элементами в том же контексте стека, которые имеют меньший уровень стека. Z-индекс равный 0 (ноль) означает то же самое, что и auto, но имеется отличие, к которому я скоро вернусь. Отрицательное целое значение Z-индекса присваивает уровень стека "позади" уровня стека предка.

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

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

  • Фон и границы элементов, которые формируют контекст стека
  • Позиционированные потомки с отрицательными уровнями стека
  • Потомки блочного уровня в нормальном потоке
  • Плавающие потомки
  • Потомки строкового уровня в нормальном потоке
  • Позиционированные потомки с уровнем стека, заданным как auto или 0 (ноль)
  • Позиционированные потомки с положительными уровнями стека
  • Выделенные позиции являются элементами, уровень стека которых можно изменять с помощью свойства z-index.

    Все это может быть достаточно сложно вообразить, поэтому давайте сделаем несколько практических экспериментов для иллюстрации Z-индекса. 1. Начнем с добавления следующей выделенной строки в пример документа:

    <body>
      <div id="outer">
        <div id="inner"></div>
        <div id="second"></div>
      </div>
    </body>

    2. Затем необходимо восстановить код CSS, так чтобы #outer был охватывающим блоком, и задать непроцентные размеры для #inner. Давайте сделаем также #outer немного выше, чтобы было больше пространства для эксперимента. Сделайте в правилах следующие выделенные изменения:

    #outer {
      margin: 5em;
      border: 1px solid #f00;
      height: 8em;
      position: relative;
    }
    
    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: absolute;
      left: 1em;
    }

    3. Добавьте также правило для элемента #second:

    #second {
      width: 5em;
      height: 5em;
      background-color: #00f;
      position: absolute;
      top: 1em;
      left: 2em;
    }

    4. Сохраните и перезагрузите документ, и вы увидите ярко синий бокс перекрывающий серый бокс. Оба бокса имеют один уровень стека ( auto, начальное значение, которое означает уровень стека 0), но синий бокс изображается перед серым боксом, так как он появляется позже в исходном коде. Можно сделать так, чтобы первый бокс выводился сверху, задавая для него положительный уровень стека. Необходимо задать его просто больше 0 - нет никакой необходимости использовать такие значения как 10000. Добавьте следующую выделенную строку в правило #inner:

    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: absolute;
      left: 1em;
      z-index: 1;
    }

    5. Сохраните и перезагрузите, и теперь вы увидите, что серый бокс выводится сверху синего.

    Локальные контексты стеков

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

    Каждый элемент, z-индекс которого определен как целое число, создает новый, "локальный", контекст стека, в котором сам элемент имеет уровень стека 0. В этом состоит различие, о котором говорилось ранее между z-index: auto и z-index: 0. Первый из них не создает новый контекст стека, а второй создает.

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

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

    Локальный контекст стека аналогичен такому конверту. Он содержит связанные элементы вместе и не позволяет другим элементам появится между ними. Можно отсортировать контент в каждом конверте требуемым образом, но этот порядок сортировки применяется только в этом конверте, и не распространяется на стек бумаг в целом. Стек содержит теперь смесь несвязанных бумаг (элементов с уровнем стека auto ), и конвертов (элементов с целочисленным уровнем стека). Конверты с положительными уровнями стека лежат поверх несвязанных бумаг, в то время как конверты с отрицательными уровнями стека окажутся внизу пачки.

    Каждый раз, когда целое значение присваивается свойству z-index элемента, создается "конверт", который содержит этот элемент и его потомков.

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

    1. Начнем с добавления некоторого контента в два внутренних элемента - добавьте выделенные строки в документ HTML:

    <div id="inner">
      <span></span>
    </div>
    <div id="second">
      <span></span>
    </div>

    2. Добавьте правило CSS, которое будет применяться к обоим этим элементам span:

    span {
      position: absolute;
      top: 2em;
      left: 2em;
      width: 3em;
      height: 3em;
    }

    Оно делает элементы span абсолютно позиционированными и задает их позиции и размеры. Хотя подождите секунду - элементы span являются строковыми - как можно определить размеры для строковых элементов? Ответ состоит в том, что абсолютно позиционированные элементы, подобно плавающим элементам, автоматически генерируют блочные боксы.

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

    3. Давайте теперь добавим немного цвета в элементы span, чтобы можно было видеть, где они появляются. Добавьте следующие правила в таблицу стилей:

    #inner span {
      background-color: #ff0;
    }
    
    #second span {
      background-color: #0ff;
    }

    4. Сохраните и перезагрузите документ, и вы должны увидеть желтый квадрат в нижнем правом углу большего по размеру серого квадрата, и голубой квадрат в нижнем правом углу большего по размеру синего квадрата. Серый и желтый квадраты появятся перед синим и голубым квадратами, так как серый квадрат имеет z-index:1.

    5. Что если нам нужно, чтобы голубой квадрат был перед всеми другими квадратами? Для этого нужно только задать для него более высокий уровень стека, чем у серого квадрата. В действительности достаточно задать ему такой же уровень стека, как и у серого квадрата, так как голубой квадрат появляется в разметке позже. Давайте проверим это - сделайте следующее изменение в коде CSS:

    #second span {
      background-color: #0ff;
      z-index: 1;
    }

    6. Сохраните и перезагрузите документ. Если используемый браузер правильно поддерживает рекомендацию CSS, то голубой квадрат должен теперь быть впереди.

    Серый квадрат имеет свойство z-index:1, что означает, что он создает локальный контекст стека. Другими словами, вы создали один из таких "конвертов" и поместили внутрь серый квадрат и его желтый квадрат потомков.

    Запутались? Следующий эксперимент должен сделать все понятнее.

    1. Задайте большой уровень стека для желтого квадрата, чтобы вывести его вперед -- сделайте следующие изменения в коде CSS:

    #inner span {
      background-color: #ff0;
      z-index: 4;
    }

    2. Если сохранить и перезагрузить документ, вы увидите … вообще никаких изменений! Уровень стека, который был определен для желтого квадрата, применяется в локальном контексте стека, созданном серым квадратом - желтый квадрат находится в конверте вместе со своим серым предком. Можно было бы переместить голубой квадрат вперед, так как его предок (синий квадрат) не создает локальный контекст стека - он имеет неявно подразумеваемое свойство z-index:auto. Синий квадрат является свободным документом в стеке. Желтый и голубой квадраты находятся в действительности в небольших конвертах сами по себе (они имеют целочисленный уровень стека и создают свои собственные локальные контексты стеков)

    3. Если синий квадрат создает локальный контекст стека, вы не сможете переместить голубой квадрат вперед, если не переместите также вперед его предка (синий квадрат). Давайте попробуем это сделать - сделайте следующие изменения в коде CSS:

    #inner {
      
      ...
      
      z-index: 2;
    }
    
    #second {
      
      ...
      
      z-index: 1;
    }
    
    #second span {
      
      ...
      
      z-index: 3;
    }

    4. Сохраните и перезагрузите. Теперь серый квадрат и синий квадрат создают локальные контексты стеков, предоставляя нам два конверта. Внизу стека находится конверт с уровнем стека 1, содержащий два внутренних конверта (синий квадрат и голубой квадрат). Вверху стека находится конверт с уровнем стека 2, содержащий два внутренних конверта (серый квадрат и желтый квадрат). В первом конверте синий квадрат имеет локальный уровень стека 0, и поэтому появляется позади голубого квадрата, который имеет локальный уровень стека 3. Во втором конверте серый квадрат имеет локальный уровень стека 0, и поэтому появится позади желтого квадрата с локальным уровнем стека 4. рис 37.1 показывает четыре бокса и два контекста локального стека по сторонам, вдоль оси Z.(рис 37.1) Иллюстрация различных контекстов стеков. Элементы, появляющиеся внутри "2" всегда будут появляться перед всеми элементами внутри "1". Затем внутри каждого контекста стека элементы с большим значением z-index появятся перед элементами с меньшим значением z-index. Если два элемента имеют одинаковое значение z-index, то элемент, который появляется в разметке позже будет находиться впереди

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

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

    Фиксированное позиционирование

    Элемент с заданным свойством position:fixed фиксируется относительно области просмотра. Он остается там, где есть, даже если документ прокручивается. Для media="print" фиксированный элемент будет повторяться на каждой печатной странице.

    Отметим, что Internet Explorer версии 6 и более старых версий вообще не поддерживает фиксированное позиционирование. При использовании одного из этих браузеров вы не сможете увидеть результаты примеров из этого раздела.

    В то время как позиция и размеры элемента с position:absolute определяются относительно его объемлющего блока, позиция и размеры элемента с position:fixed всегда определяются относительно начального объемлющего блока. Это обычно будет область просмотра: окно браузера или бокс страницы бумаги.

    Чтобы продемонстрировать это, в примере ниже мы сделаем один из элементов фиксированным. Другой элемент сделаем очень высоким, чтобы вызвать появление полосы прокрутки, чтобы можно было легче увидеть создаваемый результат.

    1. Сделайте следующие изменения в коде CSS:

    #inner {
      width: 5em;
      height: 5em;
      background-color: #999;
      position: fixed;
      top: 1em;
      left: 1em;
    }
    
    #second {
      width: 5em;
      height: 150em;
      background-color: #00f;
      position: absolute;
      top: 1em;
      left: 2em;
    }

    2. Сохраните и перезагрузите документ. Если вертикальная полоса прокрутки не появится, увеличьте значение height для #second. (Какой, однако, должен быть огромный монитор?)

    Высокий синий элемент расширяется ниже окна. Прокрутите страницу вниз, и удерживайте взгляд на сером квадрате в верхнем левом углу. #inner теперь зафиксирован в позиции 1em от верха окна и 1em от левой стороны, поэтому при прокрутке серый бокс остается в одном и том же месте на экране.

    Заключение

    Абсолютно позиционированные элементы полностью удаляются из потока документа. Они будут перекрывать другой контент, если не выделить для них пространство. Если все элементы потомки контейнера абсолютно позиционированы, высота предка будет схлопываться до нуля.

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

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

    Позиции каждого края абсолютно позиционированного элемента можно определить с помощью свойств top, right, bottom и left. Значение каждого свойства определяет расстояние от этого края до соответствующего края объемлющего блока элемента.

    Все позиционированные элементы изображаются на некотором уровне стека в контексте стека. Можно изменить уровень стека позиционированного элемента с помощью свойства z-index. Когда z-index определен как целочисленное значение, элемент создает локальный контекст стека для своих потомков.

    Контрольные вопросы

  • Отмените изменения в примере с фиксированным позиционированием и затем измените порядок стека четырех абсолютно позиционированных квадратов, так чтобы серый квадрат был внизу, а затем шли синий, желтый и голубой квадраты в данном порядке. (Совет: удалите все объявления z-index и начните сначала.)
  • Переместите желтый квадрат вверх и вправо, задавая top:-1em и left:8em. Затем сделайте так, чтобы он появился позади элемента #outer, чтобы красная граница пересекала желтый квадрат.
  • Повторите трех-столбцовую компоновку, созданную в статье о статическом и относительном позиционировании, используя вместо этого абсолютное позиционирование. Так как будет невозможно создать нижний колонтитул во всю ширину, можно удалить элемент #footer, но больше ничего изменять в разметке не разрешается (кроме ссылки на таблицу стилей).
  • Модифицируйте компоновку из предыдущего упражнения, чтобы навигация использовала фиксированное позиционирование. Нужно будет удалить автоматические горизонтальные поля на элементе body, чтобы это было возможно. Добавьте достаточно контента в основной столбец и/или боковую панель, чтобы появилась панель прокрутки, чтобы можно было проверить, что все работает.
  • Об авторе

    Томми Олссон является прагматичным пропагандистом стандартов Web и доступности, который живет в малонаселенной области центральной Швеции. Он написал свой первый документ HTML в 1993 г. и является в настоящее время техническим Web-мастером для правительственного агентства Швеции.

    Он написал пока одну книгу - Полный справочник по CSS (совместно с Полем О'Брайеном) - и поддерживает крайне нерегулярно блог с названием Кукушка-аутист (http://www.autisticcuckoo.net/).

    Материалы этого курса имеют лицензию Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.
    Вернуться к учебному плану