Позиционирование блока относительно родителя с помощью position:fixed
За столь продолжительный период верстки сегодня мне впервые пришлось столкнуться с необходимостью разместить на странице фиксированный блок (используя CSS-свойство position:fixed), который бы при скролле страницы всегда сидел в одном месте окна браузера.
Информацию по этому поводу я, естественно, почитал на разных блогах и форумах. Но все решения, которые я встретил, описывают немного не то, что понадобилось мне. Они описывают, как зафиксировать блок относительно края окна браузера, например, левый сайдбар или шапку.
У меня же стояла несколько иная задача. Имеется основной родительский блок с фиксированной шириной, выровненный по центру окна (margin: 0 auto). И необходимо справа от этого блока поместить фиксированный блок, т.е. позиционироваться он должен не от края окна браузера, а от основного блока. Вот готовый пример, о котором я веду речь.
Ниже расскажу, как я это реализовал, с учетом следующих моментов:
- во-первых, с надеждой на то, что кому-нибудь это пригодится;
- во-вторых, как шпаргалка себе на будущее (или написание поста с целью закрепления материала, аля “повторение - мать учения”, моя практика показывает, что написание поста с решением какой-либо незнакомой мне до этого задачи очень хорошо помогает запомнить это самое решение);
- в-третьих, с надеждой на то, что кто-то предложит более элегантное решение.
Итак, поехали.
HTML-код
Имеем следующую базовую разметку:
1 2 3 4 5 6 7 8 9 10 11 12 13 | <div id="wrapper"> <div id="container"> основное содержание страницы </div> <div id="fixed"> <div class="fixed"> блок, который надо зафиксировать </div> </div> </div> |
CSS-код
Имеем следующие стили для основного и контентного блоков:
1 2 3 4 5 6 7 8 9 | #wrapper { width: 642px; margin: 0 auto; padding-right: 243px; } #container { position: relative; z-index: 10; } |
Т.е. у нас имеется основной контейнер шириной 885px, размещенный по центру окна, из них 642px отдано под контент, который будет находиться в левой части, а 243px в правой части выделяем под наш фиксированный блок шириной в 240px. Собственное это и делает идентификатор #wrapper.
Хочу заострить внимание на параметрах идентификатора #container, используемого для блока с основным контентом. Необходимо обязательно обозначить уровень этого слоя выше (здесь - z-index: 10), чем слой с фиксированным блоком (это согласно условиям моего примера, в других случаях сие может быть не обязательным), иначе в FireFox’e нельзя будет выделить текст в этом блоке в части высоты, равной высоте фиксированного блока.
Чтобы получить возможность привязать фиксируемый блок к основному контентному, я сначала задал фиксируемому блоку соответствующее позиционирование (position: fixed), растянув на всю ширину окна браузера, а затем поместил в него еще один блок, к которому применил абсолютное позиционирование относительно зафиксированного родительского блока, т.е. получилось следующее:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #fixed { position: fixed; top: 0; left: 0; width: 100%; } .fixed { position: relative; width: 240px; margin: 0 auto; top: 10px; left: 323px; } |
Подобрав отступ с помощью свойства left: 323px; к блоку .fixed, отцентрированному относительно окна браузера (margin: 0 auto;), я сдвинул фиксируемый блок в предназначенное для него место.
В результате у меня получилось то, что я и хотел. Смотрим пример всего описанного выше.
Данный пример прекрасно работает в следующих браузерах: Opera, FireFox, Safari, IE7, но не работает в…
Internet Explorer 6
Ну а как же без него? :) Само-знамо, курилка даже не представляет, ЧТО есть значение position: fixed, поэтому опять приходится латать его дыры его же ява-скриптами.
Чтобы укротить IE6 для нашей задачи, необходимо, во-первых, вместо position: fixed использовать абсолютное позиционирование position: absolute, во-вторых, применить expression, который и фиксирует блок. И поместим код в условные комментарии.
Вот что у нас получилось:
1 2 3 4 5 6 7 8 9 10 | <!--[if lt IE 7]> <style type="text/css"> #fixed { position: absolute; top: expression(parseInt(document.documentElement.scrollTop, 0) + "px"); left: 50%; margin-left: -321px; } </style> <![endif]--> |
Объясняю, для чего здесь понадобились свойства left: 50%; и margin-left: -321px;. Дело в том, что, если использовать тот же самый отступ слева, что и для других браузеров, (left: 323px;), то фиксированный блок в IE6 ведет себя неправильно - при сужении окна браузера он смещается вправо от основного блока. Поэтому при помощи left: 50%; (данное свойство имеет здесь решающее значение, выявил “методом тыка”) и следующего дополнительного отрицательного отступа блок возвращается на предназначенное ему место.
Все. Теперь и в IE6 мы наблюдаем тот же результат, что и в остальных браузерах.
Однако, если посмотрите на пример в этом браузере, то заметите следующий артефакт - при прокручивании страницы блок некрасиво подергивается. Чтобы устранить данный недостаток, необходимо тегу body назначить прозрачный фоновый рисунок с фиксированным позиционированием, т.е. вот так:
1 2 3 | body { background: url(i/pixel.gif) fixed; } |
Что интересно, даже не обязательно наличие картинки pixel.gif на сервере, достаточно просто этой записи, чтобы дергание исчезло.
К сожалению, не всегда можно будет воспользоваться данным исправлением, поскольку фон body уже может быть занят элементом дизайна сайта. Тогда этот грех останется за IE6.
Вот, собственно, и все, о чем хотелось сказать в настоящей статье.
* * *
Отличный подарок на день рождения мальчику - игрушки лего, которые в большом ассортименте представлены в интернет-магазине “Lego для всех”. Осуществляется доставка как в пределах России, так и по СНГ.
Дмитрий здравствуйте (не надеюсь получить помощь но все же напишу), на сайте http://www.brizmotors.ru добавил div=”help” с position:fixed; работает во всех браузерах, включая IE 6-8 но на странице с товаром например здесь: http://www.brizmotors.ru/equipment/marine_engines/4000/4341_srm87/ position:fixed не срабатывает только в IE.
Затрудняюсь ответить.