Позиционирование блока относительно родителя с помощью position:fixed
За столь продолжительный период верстки сегодня мне впервые пришлось столкнуться с необходимостью разместить на странице фиксированный блок (используя CSS-свойство position:fixed
), который бы при скролле страницы всегда сидел в одном месте окна браузера.
Информацию по этому поводу я, естественно, почитал на разных блогах и форумах. Но все решения, которые я встретил, описывают немного не то, что понадобилось мне. Они описывают, как зафиксировать блок относительно края окна браузера, например, левый сайдбар или шапку.
У меня же стояла несколько иная задача. Имеется основной родительский блок с фиксированной шириной, выровненный по центру окна (margin: 0 auto
). И необходимо справа от этого блока поместить фиксированный блок, т.е. позиционироваться он должен не от края окна браузера, а от основного блока. Вот готовый пример, о котором я веду речь.
Ниже расскажу, как я это реализовал, с учетом следующих моментов:
- во-первых, с надеждой на то, что кому-нибудь это пригодится;
- во-вторых, как шпаргалка себе на будущее (или написание поста с целью закрепления материала, аля “повторение – мать учения”, моя практика показывает, что написание поста с решением какой-либо незнакомой мне до этого задачи очень хорошо помогает запомнить это самое решение);
- в-третьих, с надеждой на то, что кто-то предложит более элегантное решение.
Итак, поехали.
HTML-код
Имеем следующую базовую разметку:
<div id="wrapper">
<div id="container">
основное содержание страницы
</div>
<div id="fixed">
<div class="fixed">
блок, который надо зафиксировать
</div>
</div>
</div>
CSS-код
Имеем следующие стили для основного и контентного блоков:
#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
), растянув на всю ширину окна браузера, а затем поместил в него еще один блок, к которому применил абсолютное позиционирование относительно зафиксированного родительского блока, т.е. получилось следующее:
#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
, который и фиксирует блок. И поместим код в условные комментарии.
Вот что у нас получилось:
<!--[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
назначить прозрачный фоновый рисунок с фиксированным позиционированием, т.е. вот так:
body {
background: url(i/pixel.gif) fixed;
}
Что интересно, даже не обязательно наличие картинки pixel.gif
на сервере, достаточно просто этой записи, чтобы дергание исчезло.
К сожалению, не всегда можно будет воспользоваться данным исправлением, поскольку фон body
уже может быть занят элементом дизайна сайта. Тогда этот грех останется за IE6.
Вот, собственно, и все, о чем хотелось сказать в настоящей статье.
* * *
Отличный подарок на день рождения мальчику – игрушки лего, которые в большом ассортименте представлены в интернет-магазине “Lego для всех”. Осуществляется доставка как в пределах России, так и по СНГ.
Комментарии (50)
Лечится заданием минимальной ширины для блока c position:fixed
Увы не лечится
Народ, может кто подсказать как правильно сделать:
ventern.ru/321.htm
Собственно все хорошо, пока не появлется горизонтальный скрол, начинаешь его двигать туда сюда меню на месте текст ездит, смотрится кошмарно, как вылечить?
несколько дней бился с кодом затем копал интернет в поиске такой же ситуации как у меня, и вот она!
Спасибо большое автору! Его метод работает во всех браузерах, без особых нареканий (кроме ie6, даже с pixel.gif дрыгается блок). В сравнении с другими методами (которые у меня почему то не заработали) данная статья показывает ПРОСТОЕ и красивое решение вопроса.
Здравствуйте! проблема такая, у меня шапка сайта зафиксирована 155 пиксел. а я хочу в теле сайта использовать дерево каталогов и при этом хочу использовать вот этот тег
<a name="videocam1"></a><a href="#videocam1"></a>
но у меня результат он уходит под верхнее меню то есть под шапку, как мне решать эту проблему? заранее спасибо!!!!!
Дмитрий здравствуйте (не надеюсь получить помощь но все же напишу), на сайте www.brizmotors.ru добавил div=”help” с position:fixed; работает во всех браузерах, включая IE 6-8 но на странице с товаром например здесь: http://www.brizmotors.ru/equipment/marine_engines/4000/4341_srm87/ position:fixed не срабатывает только в IE.
Затрудняюсь ответить.
Автор, спасибо большое, мне очень помогла ваша статья!
Расскажите каким образом у вас зафиксирован на данной странице блок “share42”, в котором находятся кнопки соц.сетей. Интересует эффект фикса, но при этом в самом верху страницы блок не может подняться выше указанного ему места. При этом юзается скрипт
share42(‘/wp-content/themes/dimox.name/i/’,285,14)
Опишите пожалуйста этот пример, он намного более элегантнее смотрится.
Смотрите на сайте http://share42.com , либо статью http://dimox.name/socializ-floating-panel/ , там есть все необходимое.
Респект тебе!!!!
Пригодилось спасибо
странно, все сделала так как у Вас описано, все получилось, но вот много елементов на сайте стали не кликабельны: заголовки статей, блок адсенсе который я закрпила этим способом, и весь sidebar (правый).
Здравствуйте! У вас в слева значки блогов зафиксированы, очень стильно, при этом фиксируются после прокрутки шапки, подскажите как сделали? Спасибо.
http://share42.com/
к стати на счёт значков у меня они показаны только на половину другая часть где то за экраном(
Спасибо, исправил.
Наткнулся на статью с гугла, спасибо большое, но мою проблему она не помогла решить. У меня ситуация примерно такая же как у вас, только сайт резиновый, позиционирование относительно левого края мне ставить бессмысленно, а с правым не работает. Сталкивались ли вы с этой проблемой?
Спасибо за информацию. Как раз хочу нечто подобное сделать.
Cпасибо огромное, мучался 2 дня с блоком меню который нехотел отображаться в FireFox нормально и все сползало вниз, а в Opere все было нормально. Вопрос решен, снимаю шляпу пред Вами
Это то, что я так долго искал ..автор, спасибо огромное!
не понятно что за left: 323px; к блоку .fixed, и как расчитать для других width
Спасибо! Помогло.
Посмотрите что происходит при ширине окна меньше чем контейнер?
Фиксированный блок уехал :(
На моем сайте зафиксирован div со следующими css свойствами:
position:fixed;
margin-left:750px;
width:250px;
overflow:hidden;
Div позиционируется относительно родительского блока (а не окна) и при разных разрешениях остается на своем месте.
я через js делаю тока так нормально получается даже в середине страницы