Фиксированное положение, но относительно контейнера

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

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

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

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

Есть ли способ взлома или обходного пути для этого?

Ответ 1

Короткий ответ: no. (Теперь это возможно с преобразованием 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%);
}

Demos:

jsFiddle: центрируется только по горизонтали
jsFiddle: центрируется как по горизонтали, так и по вертикали
Оригинальный кредит предоставляется пользователю aaronk6 для указания мне в этом ответе

Ответ 2

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

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

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

Например:

/* 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>

Ответ 3

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

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

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

-webkit-transform: translateZ(0);

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

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

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

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

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

Но...

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

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

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

ТЕСТ

Ответ 4

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

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

Оформить боковую панель div. Он исправлен, но связан с родителем, а не с точкой просмотра окна.

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>

Ответ 5

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

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

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

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

Ответ 6

Я создал этот плагин 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();
});

Ответ 7

Просто возьмите верхний и левый стили из фиксированной позиции 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, но там будет исправлено.

Ответ 8

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

<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>

Ответ 9

РЕШЕНИЕ 2019: Вы можете использовать свойство position: sticky.

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

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

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

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

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

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

Ответ 10

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

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

Как уже было сказано выше, один ключ не устанавливает никаких позиционных настроек в элементе fixed (значения 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 и все еще есть все те элементы, связанные с верхним левым углом. Но это справедливо только в том случае, если все они размещены сначала в контейнере, поскольку эта скрипта сравнения показывает, что если диспергировать содержимое контейнера, позиционирование становится ненадежным.

Будет ли оболочка static, relative, или абсолютный в позиционировании, это не имеет значения.

Ответ 11

Вы можете попробовать мой плагин jQuery, FixTo.

Использование:

$('#mydiv').fixTo('#centeredContainer');

Ответ 12

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

Ответ 13

С чистым CSS вы не сможете это сделать; по крайней мере, я этого не делал. Однако вы можете сделать это с помощью jQuery очень просто. Я объясню свою проблему, и с небольшим изменением вы можете ее использовать.

Итак, для начала я хотел, чтобы мой элемент имел фиксированную вершину (сверху окна) и левый компонент, чтобы наследовать от родительского элемента (потому что родительский элемент центрирован). Чтобы установить левый компонент, просто поместите свой элемент в родительский элемент и установите position:relative для родительского элемента.

Затем вам нужно знать, сколько из верхней части вашего элемента есть, когда полоса прокрутки находится сверху (с нулевой прокруткой); снова есть два варианта. Во-первых, это статическое (некоторое число), или вы должны прочитать его из родительского элемента.

В моем случае это 150 пикселей от верхнего статического. Поэтому, когда вы видите 150, насколько это элемент сверху, когда мы не прокручиваем.

CSS

#parent-element{position:relative;}
#promo{position:absolute;}

JQuery

$(document).ready(function() { //This check window scroll bar location on start
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');

});
$(window).scroll(function () { //This is when the window is scrolling
    wtop=parseInt($(window).scrollTop());
    $("#promo").css('top',150+wtop+'px');
});

Ответ 14

Это легко (согласно HTML ниже)

Фокус в том, чтобы НЕ использовать верхний или левый элемент (div) с "position: fixed;". Если они не указаны, элемент "фиксированный контент" будет отображаться ОТНОСИТЕЛЬНО к охватывающему элементу (div с "position: relative;" ) INSTEAD OF относительно окна браузера!!!

<div id="divTermsOfUse" style="width:870px; z-index: 20; overflow:auto;">
    <div id="divCloser" style="position:relative; left: 852px;">
        <div style="position:fixed; z-index:22;">
            <a href="javascript:hideDiv('divTermsOfUse');">
                <span style="font-size:18pt; font-weight:bold;">X</span>
            </a>
        </div>
    </div>
    <div>  <!-- container for... -->
         lots of Text To Be Scrolled vertically...
         bhah! blah! blah!
    </div>
</div>

Выше было разрешено находить закрывающуюся кнопку "X" в верхней части большого количества текста в div с вертикальной прокруткой. "X" находится на своем месте (не перемещается с прокрученным текстом, и все же он перемещается влево или вправо с помощью контейнера-контейнера, когда пользователь изменяет ширину окна браузера! Таким образом, он "фиксирован" по вертикали, но расположен относительно охватывающий элемент по горизонтали!

Прежде чем я заработал, "X" прокручивается и исчезает из виду, когда я прокручиваю текстовый контент вниз.

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

Ответ 15

Я создал jsfiddle, чтобы продемонстрировать, как это работает с использованием transform.

HTML

<div class="left">
    Content
</div>
<div class="right">
<div class="fixedContainer">
    X
</div>
    Side bar
</div>

CSS

body {
  margin: 0;
}
.left {
  width: 77%;
  background: teal;
  height: 2000px;
}
.right {
  width: 23%;
  background: yellow;
  height: 100vh;
  position: fixed;
  right: 0;
  top: 0;
}
.fixedContainer {
    background-color:#ddd;
    position: fixed;
    padding: 2em;
    //right: 0;
    top: 0%;
    transform: translateX(-100px);
}

JQuery

$('.fixedContainer').on('click', function() {
    $('.right').animate({'width': '0px'});
  $('.left').animate({'width': '100%'});
});

https://jsfiddle.net/bx6ktwnn/1/

Ответ 16

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

<div class="container">
  <div class="scroll"></div>
  <div class="fix"></div>
</div>

CSS

.container {
  position: relative;
  flex:1;
  display:flex;
}

.fix {
  prosition:absolute;
}

Ответ 17

/* html */

/* this div exists purely for the purpose of positioning the fixed div it contains */
<div class="fix-my-fixed-div-to-its-parent-not-the-body">

     <div class="im-fixed-within-my-container-div-zone">
          my fixed content
     </div>

</div>



/* css */

/* wraps fixed div to get desired fixed outcome */
.fix-my-fixed-div-to-its-parent-not-the-body 
{
    float: right;
}

.im-fixed-within-my-container-div-zone
{
    position: fixed;
    transform: translate(-100%);
}

Ответ 18

Я сделал что-то вроде этого некоторое время назад. Я был довольно знаком с JavaScript, поэтому я уверен, что вы можете сделать лучше, но вот отправная точка:

function fixxedtext() {
    if (navigator.appName.indexOf("Microsoft") != -1) {
        if (document.body.offsetWidth > 960) {
            var width = document.body.offsetWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (document.body.offsetWidth < 960) {
            var width = 960 - document.body.offsetWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    else {
        if (window.innerWidth > 960) {
            var width = window.innerWidth - 960;
            width = width / 2;
            document.getElementById("side").style.marginRight = width + "px";
        }
        if (window.innerWidth < 960) {
            var width = 960 - window.innerWidth;
            document.getElementById("side").style.marginRight = "-" + width + "px";
        }
    }
    window.setTimeout("fixxedtext()", 2500)
}

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

Ответ 19

Это возможно, если вы используете JavaScript. В этом случае плагин jQuery Sticky-Kit:

Ответ 20

Мой проект - это .NET ASP Core 2 MVC Angular 4 шаблон с Bootstrap 4. Добавляя "липкую вершину" в основной компонент html приложения (т.е. app.component.html) в первой строке, выполните следующие действия:

<div class='row sticky-top'>
    <div class='col-sm-12'>
        <nav-menu-top></nav-menu-top>
    </div>
</div>
<div class="row">
    <div class='col-sm-3'>
        <nav-menu></nav-menu>
    </div>
    <div class='col-sm-9 body-content'>
        <router-outlet></router-outlet>
    </div>
</div>

Ответ 21

Проверьте это:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
    </head>
    <body style="width: 1000px !important;margin-left: auto;margin-right: auto">
        <div style="width: 100px; height: 100px; background-color: #ccc; position:fixed;">
        </div>
        <div id="1" style="width: 100%; height: 600px; background-color: #800000">
        </div>
        <div id="2" style="width: 100%; height: 600px; background-color: #100000">
        </div>
        <div id="3" style="width: 100%; height: 600px; background-color: #400000">
        </div>
    </body>
</html>