Позиционирование блока относительно родителя с помощью 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)

  1. 15 июля 2009 г. в 15:04

    правый блок уплывает под основной контент, при уменьшении ширины

    Да, я знаю. Но этого не избежать, по крайней мере, я не знаю способа для устранения данного недостаток.

    Лечится заданием минимальной ширины для блока c position:fixed

    1. Pavel
      1 ноября 2013 г. в 11:06 / ответ на коммент tapazukk

      Увы не лечится

  2. Vent
    11 апреля 2010 г. в 23:34

    Народ, может кто подсказать как правильно сделать:
    ventern.ru/321.htm
    Собственно все хорошо, пока не появлется горизонтальный скрол, начинаешь его двигать туда сюда меню на месте текст ездит, смотрится кошмарно, как вылечить?

  3. Daiver
    14 октября 2010 г. в 00:30

    несколько дней бился с кодом затем копал интернет в поиске такой же ситуации как у меня, и вот она!
    Спасибо большое автору! Его метод работает во всех браузерах, без особых нареканий (кроме ie6, даже с pixel.gif дрыгается блок). В сравнении с другими методами (которые у меня почему то не заработали) данная статья показывает ПРОСТОЕ и красивое решение вопроса.

  4. Даурен
    18 января 2012 г. в 10:36

    Здравствуйте! проблема такая, у меня шапка сайта зафиксирована 155 пиксел. а я хочу в теле сайта использовать дерево каталогов и при этом хочу использовать вот этот тег

    <a name="videocam1"></a><a href="#videocam1"></a>

    но у меня результат он уходит под верхнее меню то есть под шапку, как мне решать эту проблему? заранее спасибо!!!!!

  5. Евгений
    18 января 2012 г. в 13:29

    Дмитрий здравствуйте (не надеюсь получить помощь но все же напишу), на сайте www.brizmotors.ru добавил div=”help” с position:fixed; работает во всех браузерах, включая IE 6-8 но на странице с товаром например здесь: http://www.brizmotors.ru/equipment/marine_engines/4000/4341_srm87/ position:fixed не срабатывает только в IE.

    1. 18 января 2012 г. в 14:00 / ответ на коммент Евгений

      Затрудняюсь ответить.

  6. Ксюша
    7 февраля 2012 г. в 01:18

    Автор, спасибо большое, мне очень помогла ваша статья!

  7. Максим
    5 марта 2012 г. в 19:54

    Расскажите каким образом у вас зафиксирован на данной странице блок “share42”, в котором находятся кнопки соц.сетей. Интересует эффект фикса, но при этом в самом верху страницы блок не может подняться выше указанного ему места. При этом юзается скрипт
    share42(‘/wp-content/themes/dimox.name/i/’,285,14)

    Опишите пожалуйста этот пример, он намного более элегантнее смотрится.

    1. 5 марта 2012 г. в 20:11 / ответ на коммент Максим

      Смотрите на сайте http://share42.com , либо статью http://dimox.name/socializ-floating-panel/ , там есть все необходимое.

  8. Fedor
    19 апреля 2012 г. в 11:51

    Респект тебе!!!!
    Пригодилось спасибо

  9. copika
    28 июня 2012 г. в 12:14

    странно, все сделала так как у Вас описано, все получилось, но вот много елементов на сайте стали не кликабельны: заголовки статей, блок адсенсе который я закрпила этим способом, и весь sidebar (правый).

  10. 21 июля 2012 г. в 13:30

    Здравствуйте! У вас в слева значки блогов зафиксированы, очень стильно, при этом фиксируются после прокрутки шапки, подскажите как сделали? Спасибо.

  11. joker
    18 сентября 2012 г. в 12:22

    к стати на счёт значков у меня они показаны только на половину другая часть где то за экраном(

    1. 18 сентября 2012 г. в 12:37 / ответ на коммент joker

      Спасибо, исправил.

  12. Олег
    30 октября 2012 г. в 09:41

    Наткнулся на статью с гугла, спасибо большое, но мою проблему она не помогла решить. У меня ситуация примерно такая же как у вас, только сайт резиновый, позиционирование относительно левого края мне ставить бессмысленно, а с правым не работает. Сталкивались ли вы с этой проблемой?

  13. 2 ноября 2012 г. в 16:11

    Спасибо за информацию. Как раз хочу нечто подобное сделать.

  14. KOT
    10 декабря 2012 г. в 21:25

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

  15. Павел
    4 марта 2013 г. в 08:39

    Это то, что я так долго искал ..автор, спасибо огромное!

  16. новичек
    13 октября 2013 г. в 11:13

    не понятно что за left: 323px; к блоку .fixed, и как расчитать для других width

  17. Виталий
    15 октября 2013 г. в 22:06

    Спасибо! Помогло.

  18. Pavel
    1 ноября 2013 г. в 11:05

    Посмотрите что происходит при ширине окна меньше чем контейнер?
    Фиксированный блок уехал :(

  19. Иван
    23 июля 2014 г. в 17:16

    На моем сайте зафиксирован div со следующими css свойствами:

    position:fixed;
    margin-left:750px;
    width:250px;
    overflow:hidden;

    Div позиционируется относительно родительского блока (а не окна) и при разных разрешениях остается на своем месте.

  20. Insatiable
    18 августа 2014 г. в 02:18

    я через js делаю тока так нормально получается даже в середине страницы

Ваш комментарий

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код