'transform3d' не работает с позицией: фиксированные дети
У меня есть ситуация, когда в нормальных условиях CSS фиксированный div будет расположен именно там, где он указан (top:0px
, left:0px
).
Это, кажется, не соблюдается, если у меня есть родитель, у которого есть translate3d преобразование. Я что-то не вижу? Я пробовал другие webkit-трансформации, такие как стиль и параметры трансформации источника, но мне не повезло.
Я приложил JSFiddle с примером, где я ожидал, что желтая рамка будет в верхнем углу страницы, а не внутри элемента контейнера.
Ниже вы можете найти упрощенную версию скрипки:
#outer {
position:relative;
-webkit-transform:translate3d(0px, 20px , 0px);
height: 300px;
border: 1px solid #5511FF;
padding: 10px;
background: rgba(100,180,250, .8);
width: 80%;
}
#middle{
position:relative;
border: 1px dotted #445511;
height: 300px;
padding: 5px;
background: rgba(250,10,255, .6);
}
#inner {
position: fixed;
top: 0px;
box-shadow: 3px 3px 3px #333;
height: 20px;
left: 0px;
background: rgba(200,180,80, .8);
margin: 5px;
padding: 5px;
}
<div id="container">
Blue: Outer, <br>
Purple: Middle<br>
Yellow: Inner<br>
<div id="outer">
<div id="middle">
<div id="inner">
Inner block
</div>
</div>
</div>
</div>
Ответы
Ответ 1
Это связано с тем, что transform
создает новую локальную систему координат по спецификации W3C:
В пространстве имен HTML любое значение, отличное от none
для преобразования, приводит к созданию как стекового контекста, так и содержащего блока. Объект действует как содержащий блок для фиксированных позиционированных потомков.
Это означает, что фиксированное позиционирование становится привязанным к преобразованному элементу, а не к окну просмотра.
В настоящий момент я не знаю, о чем я знаю.
Также описывается статья Эрика Мейера: Исправление фиксированных элементов с помощью CSS-преобразований.
Ответ 2
У меня было мерцание на моем фиксированном верхнем навигаторе, когда элементы на странице использовали преобразование, следующее применимо к моему верхнему навигатору, решило проблему с прыганием/мерцанием:
#fixedTopNav {
position: fixed;
top: 0;
transform: translateZ(0);
-webkit-transform: translateZ(0);
}
Благодаря этому ответу на SO
Ответ 3
Как предложил Брадоерго, просто оставьте окно scrollTop
и добавьте его в верхнюю позицию абсолютного положения, например:
function fix_scroll() {
var s = $(window).scrollTop();
var fixedTitle = $('#fixedContainer');
fixedTitle.css('position','absolute');
fixedTitle.css('top',s + 'px');
}fix_scroll();
$(window).on('scroll',fix_scroll);
Все это сработало для меня.
Ответ 4
В Firefox и Safari вы можете использовать position: sticky;
вместо position: fixed;
, но он не будет работать в других браузерах. Для этого вам нужен javascript.
Ответ 5
На мой взгляд, лучший способ справиться с этим - применить тот же самый перевод, но отделить дочерние элементы, которые должны быть зафиксированы от их родительского (переведенного) элемента; и затем примените перевод к div внутри position: fixed
обертка.
Результаты выглядят примерно так (в вашем случае):
<div style='position:relative; border: 1px solid #5511FF;
-webkit-transform:translate3d(0px, 20px , 0px);
height: 100px; width: 200px;'>
</div>
<div style='position: fixed; top: 0px;
box-shadow: 3px 3px 3px #333;
height: 20px; left: 0px;'>
<div style='-webkit-transform:translate3d(0px, 20px, 0px);'>
Inner block
</div>
</div>
JSFiddle: https://jsfiddle.net/hju4nws1/
Хотя это может не быть идеальным для некоторых случаев использования, обычно, если вы исправляете div, вам, возможно, будет безразлично, какой элемент является его родителем/где он находится в дереве наследования в вашем DOM, и, похоже, он решает большую часть головной боли - в то же время позволяя как translate
и translate
position: fixed
жить в (относительной) гармонии.
Ответ 6
Я столкнулся с той же проблемой. Единственное различие заключается в том, что мой элемент с "position: fixed" имел свои свойства стиля "top" и "left", установленные из JS. Поэтому я смог применить исправление:
var oRect = oElement.getBoundingClientRect();
Объект oRect будет содержать реальные (относительно порта представления) верхние и левые координаты. Таким образом, вы можете настроить свои фактические свойства oElement.style.top и oElement.style.left.
Ответ 7
У меня такая же проблема, и я считаю, что вокруг это работает.
Я использую snap.js, и я хочу, чтобы один из дочерних div контейнера содержимого был зафиксирован на его позиции. Однако, когда ящик открывается, JavaScript запускает свойство transform: translate3d для родительского контейнера, и это также влияет на фиксированный дочерний элемент (фиксированный элемент перемещается вместе со своим родителем и остается фиксированным в новой позиции).
С учетом сказанного фиксированное свойство становится частично бесполезным. Чтобы решить эту проблему, может быть добавлен прослушиватель событий, который будет запускать отдельный tranform: translate3d для фиксированного дочернего div. И направление этого перевода должно быть противоположно родительскому преобразованию: translate3d.
Единственная проблема заключается в том, что я не знаю, как ее написать, и было бы здорово, если бы кто-то взял на нее удар.
Ответ 8
У меня есть боковая панель с холстом, которая использует -webkit-transform: translate3d. Это мешало мне помещать фиксированный нижний колонтитул на страницу. Я решил проблему, настроив класс на html-странице, который добавлен в тег при инициализации боковой панели, а затем написал css: not qualifier, чтобы указать "-webkit-transform: none;" в тег html, когда этот класс отсутствует в теге html. Надеюсь, это поможет кому-то там с этой же проблемой!
Ответ 9
Попробуйте применить противоположное преобразование к дочернему элементу:
<div style='position:relative; border: 1px solid #5511FF;
-webkit-transform:translate3d(0px, 20px , 0px);
height: 100px; width: 200px;'>
<div style='position: fixed; top: 0px;
-webkit-transform:translate3d(-100%, 0px , 0px);
box-shadow: 3px 3px 3px #333;
height: 20px; left: 0px;'>
Inner block
</div>
</div>
Ответ 10
Добавьте динамический класс, пока элемент трансформируется. $('#elementId').addClass('transformed')
. Затем продолжайте объявлять в CSS,
.translat3d(@x, @y, @z) {
-webkit-transform: translate3d(@X, @y, @z);
transform: translate3d(@x, @y, @z);
//All other subsidaries as -moz-transform, -o-transform and -ms-transform
}
затем
#elementId {
-webkit-transform: none;
transform: none;
}
затем
.transformed {
#elementId {
.translate3d(0px, 20px, 0px);
}
}
Теперь position: fixed
если для дочернего элемента заданы значения свойств top
и z-index
просто работают нормально и остаются неизменными до преобразования родительского элемента. Когда преобразование отменено, дочерний элемент снова появляется как исправлено. Это должно облегчить ситуацию, если вы фактически используете боковую панель навигации, которая включает и закрывает при нажатии, и у вас есть набор вкладок, который должен оставаться липким при прокрутке страницы вниз.
Ответ 11
Один из способов борьбы с этим - применить одно и то же преобразование к фиксированному элементу:
<br>
<div style='position:relative; border: 1px solid #5511FF;
-webkit-transform:translate3d(0px, 20px , 0px);
height: 100px; width: 200px;'>
<div style='position: fixed; top: 0px;
-webkit-transform:translate3d(0px, 20px , 0px);
box-shadow: 3px 3px 3px #333;
height: 20px; left: 0px;'>
Inner block
</div>
</div>
Ответ 12
Если вы работаете на мобильном телефоне с меню offcanvas, возможно, этот код вам поможет.
$('#toggle-button').click(function () {
slideout.toggle();
// Sticky menu with off canvas menu (for mobile)
var isMenuDisplaced = $('.sticky-menu').hasClass('is-displaced');
if (isMenuDisplaced === false) {
$('.sticky-menu').addClass('is-displaced');
var scrollTopPosition = $(window).scrollTop();
$('.sticky-menu').css('position', 'absolute');
$('.sticky-menu').css('top', scrollTopPosition + 'px');
}
else {
window.setTimeout(function () {
$('.sticky-menu').removeClass('is-displaced');
$('.sticky-menu').css('position', 'fixed');
$('.sticky-menu').css('top', 0);
}, 400);
}
})