Фиксированная позиция, но относительно контейнера - PullRequest
567 голосов
/ 22 июля 2011

Я пытаюсь исправить div, чтобы он всегда прилипал к верхней части экрана, используя:

position: fixed;
top: 0px;
right: 0px;

Однако div находится внутри центрированного контейнера. Когда я использую position:fixed, он фиксирует div относительно окна браузера, например, напротив правой стороны браузера. Вместо этого он должен быть зафиксирован относительно контейнера.

Я знаю, что position:absolute можно использовать для исправления элемента относительно div, но когда вы прокручиваете страницу вниз, элемент исчезает и не прилипает к вершине, как с position:fixed.

Есть ли хак или обходной путь для достижения этой цели?

Ответы [ 21 ]

375 голосов
/ 22 июля 2011

Краткий ответ: нет. (Теперь это возможно с помощью преобразования CSS. См. Редактирование ниже)

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

#fixedContainer {
  position: fixed;
  width: 600px;
  height: 200px;
  left: 50%;
  top: 0%;
  margin-left: -300px; /*half the width*/
}

http://jsfiddle.net/HFjU6/1/

Редактировать (03/2015):

Это устаревшая информация. Теперь возможно центрировать содержимое динамического размера (по горизонтали и вертикали) с помощью волшебного преобразования CSS3. Применяется тот же принцип, но вместо использования поля для смещения контейнера вы можете использовать translateX(-50%). Это не работает с вышеупомянутым трюком на полях, потому что вы не знаете, сколько его сместить, если ширина не фиксирована, и вы не можете использовать относительные значения (например, 50%), потому что это будет относительно родителя, а не элемент, к которому он применяется. transform ведет себя по-разному. Его значения относятся к элементу, к которому они применяются. Таким образом, 50% для transform означает половину ширины элемента, а 50% для поля - половину ширины родительского элемента. Это IE9 + решение

Используя код, похожий на приведенный выше пример, я воссоздал тот же сценарий, используя полностью динамические ширину и высоту:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 0%;
    transform: translateX(-50%);
}

Если вы хотите, чтобы он был отцентрирован, вы можете сделать это тоже:

.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
}

Демонстрация:

jsFiddle: только по центру по горизонтали
jsFiddle: по горизонтали и вертикали
Первоначальная благодарность пользователю aaronk6 за указание на это в этом ответе

165 голосов
/ 06 августа 2012

На самом деле это возможно, и принятый ответ касается только централизации, что достаточно просто.Кроме того, вам действительно не нужно использовать JavaScript.

Это позволит вам справиться с любым сценарием:

Настройте все так, как вы хотите, если вы хотите позиционировать: абсолютное внутри позиции: относительноеконтейнер, а затем создайте новую фиксированную позицию div внутри div с помощью position: absolute, но not установите его свойства top и left.Затем он будет исправлен в любом месте относительно контейнера.

Например:

/* Main site body */
.wrapper {
    width: 940px;
    margin: 0 auto;
    position: relative; /* Ensure absolute positioned child elements are relative to this*/
}

/* Absolute positioned wrapper for the element you want to fix position */
.fixed-wrapper {
    width: 220px;
    position: absolute;
    top: 0;
    left: -240px; /* Move this out to the left of the site body, leaving a 20px gutter */
}

/* The element you want to fix the position of */
.fixed {
    width: 220px;
    position: fixed;
    /* Do not set top / left! */
}
<div class="wrapper">
    <div class="fixed-wrapper">
        <div class="fixed">
            Content in here will be fixed position, but 240px to the left of the site body.
        </div>
    </div>
</div>

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

127 голосов
/ 08 апреля 2013

Да, согласно спецификации, есть способ.

Хотя я согласен с тем, что Грэм Блэквуд должен быть принятым ответом, поскольку он практически решает проблему, следует отметить, что фиксированный элемент может располагаться относительно его контейнера.

Я случайно заметил, что при применении

-webkit-transform: translateZ(0);

к телу, он сделал фиксированного потомка относительно него (вместо области просмотра). Так что мои фиксированные элементы left и top теперь были относительно контейнера.

Итак, я провел некоторое исследование и обнаружил, что проблема уже была рассмотрена Эриком Мейером и даже если это показалось «уловкой», оказалось, что это часть спецификаций:

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

http://www.w3.org/TR/css3-transforms/

Итак, если вы примените какое-либо преобразование к родительскому элементу, он станет содержащим блоком.

Но ...

Проблема в том, что реализация кажется ошибочной / креативной, поскольку элементы также перестают вести себя как фиксированные (даже если этот бит не является частью спецификации).

Такое же поведение будет обнаружено в Safari, Chrome и Firefox, но не в IE11 (где фиксированный элемент все еще останется фиксированным).

Еще одна интересная (недокументированная) вещь заключается в том, что когда внутри преобразованного элемента содержится фиксированный элемент, тогда как его свойства top и left теперь будут связаны с контейнером, соблюдая свойство box-sizing, его контекст прокрутки. будет расширяться за границу элемента, как если бы размер рамки был установлен на border-box. Для некоторых креативщиков это может стать игрушкой:)

TEST

58 голосов
/ 22 марта 2013

Ответ - да, если вы не установили left: 0 или right: 0 после того, как вы установили положение div на фиксированное значение.

http://jsfiddle.net/T2PL5/85/

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

body { background: #ccc; }

.wrapper {
    margin: 0 auto;
    height: 1400px;
    width: 650px;
    background: green;
}

.sidebar {
    background-color: #ddd;
    float: left;
    width: 300px;
    height: 100px;
    position: fixed;
}

.main {
    float: right;
    background-color: yellow;
    width: 300px;
    height: 1400px;
}

<div class="wrapper">wrapper
    <div class="sidebar">sidebar</div>
    <div class="main">main</div>
</div>
31 голосов
/ 19 апреля 2013

position: sticky - это новый способ позиционирования элементов, концептуально похожий на position: fixed. Разница в том, что элемент с position: sticky ведет себя как position: relative в пределах своего родителя, пока в окне просмотра не будет достигнут заданный порог смещения.

В Chrome 56 (в настоящее время бета-версия по состоянию на декабрь 2016 года, стабильная в январе 2017 года) позиция: липкая вернулась.

https://developers.google.com/web/updates/2016/12/position-sticky

Подробнее в Придерживайтесь своих посадок! позиция: залипание земель в WebKit .

18 голосов
/ 29 августа 2011

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

Вот ссылка на этот плагин jQuery, который может решить эту проблему:

https://github.com/bigspotteddog/ScrollToFixed

Описание этого плагина выглядит следующим образом:

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

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

Этот плагин был протестирован в Firefox 3/4, Google Chrome 10/11, Safari 5 и Internet Explorer 8/9.

Использование в вашем конкретном случае:

<script src="scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
<script src="scripts/jquery-scrolltofixed-min.js" type="text/javascript"></script>

$(document).ready(function() {
    $('#mydiv').scrollToFixed();
});
17 голосов
/ 28 марта 2012

Просто возьмите верхний и левый стили из фиксированной позиции div. Вот пример

<div id='body' style='height:200%; position: absolute; width: 100%; '>
    <div id='parent' style='display: block; margin: 0px auto; width: 200px;'>
        <div id='content' style='position: fixed;'>content</div>
    </div>
</div> 

#content div будет сидеть там, где сидит родительский div, но будет исправлено там.

12 голосов
/ 30 апреля 2012

Я должен был сделать это с рекламой, которую мой клиент хотел разместить за пределами области контента.Я просто сделал следующее, и это сработало как шарм!

<div id="content" style="position:relative; width:750px; margin:0 auto;">
  <div id="leftOutsideAd" style="position:absolute; top:0; left:-150px;">
    <a href="#" style="position:fixed;"><img src="###" /></a>
  </div>
</div>
7 голосов
/ 20 января 2018

Вы можете использовать position: sticky свойство.

Вот пример CODEPEN , демонстрирующий использование, а также его отличие от position: fixed.

Как это ведет себя, объяснено ниже:

  1. Элемент с закрепленной позицией позиционируется на основе позиции прокрутки пользователя.Он в основном действует как position: relative, пока элемент не прокручивается за пределы определенного смещения, и в этом случае он превращается в положение: исправлено.Когда он прокручивается назад, он возвращается к своей предыдущей (относительной) позиции.

  2. Он влияет на поток других элементов на странице, т.е. занимает определенное место на странице (как и position: relative).

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

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

7 голосов
/ 12 декабря 2013

Два HTML-элемента и чистый CSS (современные браузеры)

См. Этот пример jsFiddle. Измените размер и посмотрите, как фиксированные элементы даже перемещаются вместе с плавающими элементами, которые онинаходятся внутри. Используйте самую внутреннюю полосу прокрутки, чтобы увидеть, как будет работать прокрутка на сайте (фиксированные элементы остаются фиксированными).

Как многие здесь заявили, одна клавиша не устанавливает какие-либо позиционные настройки для *Элемент 1009 * (без значений top, right, bottom или left).

Вместо этого сначала мы помещаем все фиксированные элементы (обратите внимание, что в последнем блоке их четыре)в поле они должны быть расположены, например, так:

<div class="reference">
  <div class="fixed">Test</div>
  Some other content in.
</div>

Затем мы используем margin-top и margin-left, чтобы «переместить» их относительно их контейнера, что-то вроде этого CSS:

.fixed {
    position: fixed;
    margin-top: 200px; /* Push/pull it up/down */
    margin-left: 200px; /* Push/pull it right/left */
}

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

Независимо от того, является ли обертка статическое , относительное или абсолютное в позиционировании, не имеет значения.

...