'transform3d' не работает с позицией: фиксированные дети


у меня есть ситуация, когда в обычных обстоятельствах CSS фиксированный div будет расположен именно там, где он указан (top:0px,left:0px).

Это, кажется, не соблюдается, если у меня есть родитель, который имеет преобразование translate3d. Разве я ничего не вижу? Я пробовал другие варианты webkit-transform, такие как style и transform origin, но не повезло.

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

http://jsfiddle.net/GMX5H/1/

это упрощенная версия скрипка:

<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; 
                box-shadow: 3px 3px 3px #333; 
                height: 20px; left: 0px;'>
        Inner block
    </div>
</div>

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

12 115

12 ответов:

это так transform создает новую локальную систему координат, а в W3C spec:

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

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

в настоящее время нет обходного пути, о котором я знаю.

это также задокументировано в статье Эрика Мейера:Un-fixing фиксированные элементы с преобразованиями CSS.

Как предложил Bradoergo, просто получите окно 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);

это сработало для меня в любом случае.

У меня были мерцания на моем фиксированном верхнем навигаторе, когда элементы на странице использовали преобразование, следующее, примененное к моему верхнему навигатору, разрешило проблему прыжков/мерцания:

#fixedTopNav {
    position: fixed;
    top: 0;
    transform: translateZ(0);
    -webkit-transform: translateZ(0);
}

благодаря этому ответу на SO

в Firefox и Safari вы можете использовать position: sticky; вместо position: fixed; но это не будет работать в других браузерах. Для этого вам нужен javascript.

и

не найдя удовлетворительного метода для решения этой проблемы; и делая некоторые вещи вне холста (требующие перевода) - я немного покопался и обнаружил ,что (по крайней мере, для моего варианта использования) лучший способ справиться с этим-применить тот же перевод, но разбить детей, которые должны быть исправлены из их родительского (переведенного) элемента; а затем применить перевод к div внутри position: fixed фантик.

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

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

скрипка вилка:https://jsfiddle.net/hju4nws1/

хотя это может быть не идеально для некоторых случаев использования, как правило, если вы фиксируете div, вы, вероятно, могли бы меньше заботиться о том, какой элемент является его родителем/где он попадает в дерево наследования в вашем DOM, и, похоже, решает большую часть головной боли - все еще позволяя обоим translate и position: fixed жить в (относительной) гармонии.

У меня есть аналогичная проблема, и я считаю, что есть работа вокруг него. Я использую оснастку.js и я хочу, чтобы один из дочерних дивов контейнера содержимого был зафиксирован в его положении. Однако, когда ящик открывается, JavaScript запускает свойство transform: translate3d для родительского контейнера, и это также влияет на фиксированный дочерний элемент (фиксированный элемент перемещается вместе со своим родителем и остается фиксированным в новом положении).

с этим, как говорится, фиксированное свойство становится частично бесполезный. Чтобы решить эту проблему, можно добавить прослушиватель событий, который будет запускать отдельную транформу:translate3d для фиксированного дочернего div. И направление этого перевода должно быть противоположно преобразованию родителя: translate3d.

единственная проблема заключается в том, что я не знаю как это написать и было бы здорово, если кто-то принял удар на себя.

я столкнулся с той же проблемой. Единственное различие заключается в том, что мой элемент с "position: fixed" имел свои свойства стиля " top " и "left", установленные из JS. Поэтому я смог применить исправление:

var oRect = oElement.getBoundingClientRect();

объект oRect будет содержать реальные (относительно порта просмотра) верхние и левые координаты. Таким образом, вы можете настроить свой фактический oElement.стиль.топ и олемент.стиль.левые свойства.

У меня с холста боковая панель, которая использует -webkit-преобразования: translate3d. Это мешает мне устанавливать фиксированный нижний колонтитул на странице. Я решил проблему, выбрав класс на html-странице, который добавляется к тегу при инициализации боковой панели, а затем пишет CSS :not квалификатор для состояния "-webkit-transform: none;" в HTML-тег, когда этот класс отсутствует в html-теге. Надеюсь, это поможет кому-то там с этой же проблемой!

попробуйте применить противоположное преобразование к дочернему элементу:

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

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

один из способов справиться с этим-применить то же преобразование к фиксированному элементу:

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

Если вы работаете на мобильном телефоне с меню 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);
    }


})