Фиксированные позиции не работают при использовании -webkit-transform


155

Я использую -webkit-transform (и -moz-transform / -o-transform), чтобы вращать div. Также добавлено фиксированное положение, чтобы div прокручивал пользователя вниз.

В Firefox он работает нормально, но в браузерах на основе webkit он не работает. После использования -webkit-transform фиксированная позиция больше не работает! Как это возможно?


4
Демо-страница часто помогает людям отвечать на вопросы - jsbin.com позволяет создавать временные страницы, чтобы проиллюстрировать проблему, если вы не хотите давать ссылку на свой сайт.
Рич Брэдшоу

jsfiddle.net - еще один хороший пример временного бина для редактирования.
Кайл

@Rich Bradshaw jsbin.com очень хороший. Не знал этого до сих пор. Большинство моих проектов я запускаю локально, поэтому буду использовать его в следующий раз. Tnx
iSenne

7
Это не работает в Firefox вообще.
vsync

3
По-прежнему проблема в 2017 году. Кажется, они все еще придерживаются "Это функция, а не ошибка!" аргумент ...
Макс

Ответы:


87

После некоторых исследований на веб-сайте Chromium появилось сообщение об ошибке , поэтому браузеры Webkit не могут одновременно визуализировать эти два эффекта.

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

@media screen and (-webkit-min-device-pixel-ratio:0) {
  /* Webkit-specific CSS here (Chrome and Safari) */

  #transformed_div {
    /* styles here, background image etc */
  }
}

Так что сейчас вам придется делать это по старинке, пока браузеры Webkit не догонят FF.

РЕДАКТИРОВАТЬ: По состоянию на 24.10.2012 ошибка не была решена.


Похоже, что это не ошибка, а аспект спецификации из-за двух эффектов, требующих отдельных систем координат и порядков наложения. Как объяснено в этом ответе .


34
Даже спустя годы все еще не решены. Довольно грустно
Амальговинус

9
Согласно этому ответу, это не ошибка, а часть спецификации.
MichaelRushton

15
сидеть сложа
руки

29
30 августа 2017 года, капитанский бревно. Мы также столкнулись со странной аномалией, которая была описана так давно другими капитанами. Решение еще предстоит реализовать.
Luoruize

14
Это ошибка, о которой отец моего отца предупреждал.
danjones_mcr

96

Спецификация CSS Transforms объясняет это поведение. Элементы с преобразованиями действуют как содержащий блок для потомков с фиксированным положением, поэтому position: fixed под чем-то с преобразованием больше не имеет фиксированного поведения.

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


9
Это единственный полезный и правильный ответ. Прекратите переводить родительский элемент и переведите дочерние элементы, где фиксированный элемент является его частью. Вот моя скрипка: JSFIDDLE
Фальк

2
а что если я тоже хочу преобразовать фиксированный элемент?
Марк

7

Для тех, кто находит фоновые изображения, исчезают в Chrome из-за той же проблемы с background-attachment: исправлено; - это было мое решение:

// run js if Chrome is being used
if(navigator.userAgent.toLowerCase().indexOf('chrome') > -1) {
    // set background-attachment back to the default of 'scroll'
    $('.imagebg').css('background-attachment', 'scroll');

    // move the background-position according to the div's y position
    $(window).scroll(function(){

        scrollTop = $(window).scrollTop();
        photoTop = $('.imagebg').offset().top;
        distance = (photoTop - scrollTop);
        $('.imagebg').css('background-position', 'center ' + (distance*-1) + 'px');

    });
}  

6

Что-то (немного странное), которое сработало для меня, заключается в следующем position:sticky:

.fixed {
     position: sticky;
}

5
updates.html5rocks.com/2012/08/… ах да .. но пока что не очень хорошо поддерживается
coiso

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

6

Август 2016 и фиксированная позиция и анимация / трансформация все еще остаются проблемой. Единственное решение, которое сработало для меня, - это создать анимацию для дочернего элемента, которая занимает больше времени.


Пожалуйста, ответьте на новые вопросы. Эти вопросы нужны вам больше, чем человеку, который задал вопрос в 2010 году. Должно быть, они уже решили проблему, не так ли? Также на этот вопрос уже есть принятый ответ.
Umair Farooq

5
Нет! Это все еще проблема ... человек, который задал вопрос, возможно, нашел другое решение - но я нашел эту тему по причине.
defligra

Как хотите. Я оставил этот комментарий при рассмотрении первых вопросов людьми. И поскольку вы присоединились только сегодня, и это был ваш первый ответ, а также поздний ответ, поэтому я оставил этот комментарий. Я не понизил. Это хороший шанс для вас.
Umair Farooq

1
@UmairFarooq, возможно, задавать другой вопрос будет бесполезно, потому что он может быть помечен как дубликат. Я пришел сюда только с поиском Google, и я нашел этот вопрос полезным, ответ defligra тоже.
KoMah

3

На самом деле я нашел другой способ исправить эту «ошибку»:

У меня есть элемент контейнера, который содержит страницу с анимацией CSS3. Когда страница завершила анимацию, свойство css3 имеет значение: transform: translate (0,0) ;. Итак, я просто удалил эту строку, и все заработало как надо - position: fixed отображается правильно. Когда для перевода страницы применяется класс css, добавляется свойство translate и анимация css3 также работает.

Пример:

.page {
     top: 50px;
     position: absolute;
     transition: ease 0.6s all;
     /* -webkit-transform: translate(0, 0); */
     /* transform: translate(0,0); */
 }
 .page.hide {
     -webkit-transform: translate(100%, 0);
     transform: translate(-100%, 0);    
 }

Демо: http://jsfiddle.net/ZWcD9/


1
Для меня это был факт наличия этих стилей на обертке, содержащей фиксированный элемент, который препятствовал закреплению фиксированного элемента: -webkit -спектива: 1000; -webkit-transform-style: preserve-3d; Снял их и все отлично работает. В любом случае, это были сомнительные оптимизации!
Амальговинус

Удаление преобразования любым способом, пожалуй, пока лучший обходной путь. Что-то вроде постепенного появления, когда оно завершено, должно быть съемным, не влияя на внешний вид элемента. На самом деле, я не уверен, что наличие функции transformX (0) повлияло бы на производительность рендеринга, если вообще что-нибудь; его можно либо игнорировать, либо ухудшать производительность, либо улучшать его, форсируя какое-то 3D-ускорение. Кто знает. В любом случае, когда анимация завершена или даже непосредственно перед тем, как к ней добавлен фиксированный элемент, можно просто удалить классы CSS для преобразования.
Триынко

1

в моем проекте phonegap преобразование webkit -webkit-transform: translateZ (0); работал как шарм. Он уже работал в Chrome и Safari, а не в мобильном браузере. также может быть еще одна проблема - WRAPPER DIVs не завершены в некоторых случаях. мы применяем чистый класс в случае плавающих DIV.

<div class="Clear"></div> .Clear, .Clearfix{clear:both;}

1

Возможно, из-за ошибки в Chrome, поскольку я не могу воспроизвести в Safari и Firefox, но это работает в Chrome 40.0.2214.111 http://jsbin.com/hacame/1/edit?html,css,output

Это очень специфическая структура, поэтому она ни в коем случае не является универсально применимым однострочным исправлением CSS, но, возможно, кто-то может воспользоваться им, чтобы заставить его работать в Safari и Firefox.


1

У меня была эта проблема, когда я пытался реализовать ответный цвет с помощью реагирующих смахиваний (rsw). Проблема для меня заключалась в том, что RSW применяетсяtranslate(-100%, 0) к панели вкладок, которая нарушает стандартную фиксированную позицию div, добавленную на весь экран, которая при нажатии закрывает модель палитры цветов.

Для меня решение было применить противоположное преобразование к фиксированному элементу (в этом случае translate(100%, 0) это решило мою проблему. Я не уверен, полезно ли это в других случаях, но думал, что поделюсь в любом случае.

Вот пример, показывающий то, что я описал выше:

https://codepen.io/relativemc/pen/VwweEez


0

Добавление -webkit-transformк фиксированному элементу решило проблему для меня.

.fixed_element {
   -webkit-transform: translateZ(0);
   position: fixed;
   ....
} 

20
Это не сработало для меня. Можете ли вы создать демо-версию?
alex

4
Это исправило проблему для меня в Chrome, FWIW. Спасибо Рон.
Крис

3
Спасибо, это исправило проблему. Спас мою жизнь!
styke

1
@ Нил Монро, Android 2.3 - это совершенно новая история. Это не поддерживает фиксированное позиционирование вообще :)
Wiseman

8
Вот скрипка, где использование translateZ(0) НЕ работает. Это правда, что иногда это работает, я видел случаи, когда это работало. Но я все еще не могу сузить это.
Zequez

0

Вот что работает для меня на всех протестированных браузерах и мобильных устройствах (Chrome, IE, Firefox, Safari, iPad, iphone 5 и 6, Android).

img.ui-li-thumb {
    position: absolute;
    left: 1px;
    top: 50%;

    -ms-transform: translateY(-50%);
    -webkit-transform: translateY(-50%);
    -moz-transform: translateY(-50%);
    -o-transform: translateY(-50%);
    transform: translateY(-50%);
}

2
Почему отрицательные? Было бы хорошо, если бы вы предоставили комментарий о том, почему вы проголосовали за мой ответ?
Murf

0

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

<div style='position:fixed;-.*-transform:scale(2)'>...</div> //ok

<div style='-.*-transform:scale(2)'>
      <div style='position:fixed'>...</div> // broken
</div>

0

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

  let fixedEl // some node that you is position 
              // fixed inside of an element that has a transform

  const rect = fixedEl.getBoundingClientRect()
  const distanceFromWindowTop = rect.top
  const distanceFromWindwoLeft = rect.left
  let top = fixedEl.offsetTop
  let left = fixedEl.offsetLeft

  if(distanceFromWindowTop !== relativeTop) {
    top = -distanceFromWindowTop
    fixedEl.style.top = `${top}px`
  }

  if(distanceFromWindowLeft !== relativeLeft) {
    left = -distanceFromWindowLeft
    fixedEl.style.left = `${left}px`
  }

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


0

Добавьте динамический класс, пока элемент трансформируется. $('#elementId').addClass('transformed'), Затем продолжайте объявлять в CSS,

.translatX(@x) { 
     -webkit-transform: translateX(@X); 
             transform: translateX(@x);
      //All other subsidaries as -moz-transform, -o-transform and -ms-transform 
}

затем

#elementId { 
      -webkit-transform: none; 
              transform: none;
}

затем

.transformed {
    #elementId { 
        .translateX(@neededValue);
    }
}

Теперь положение: исправлено, если для дочернего элемента заданы значения свойств top и z-index, просто работают нормально и остаются неизменными, пока родительский элемент не преобразуется. Когда преобразование отменено, дочерний элемент снова появляется как исправлено. Это должно облегчить ситуацию, если вы на самом деле используете боковую панель навигации, которая включает и закрывает при щелчке, и у вас есть набор вкладок, который должен оставаться липким, когда вы прокручиваете страницу вниз.


0

в моем случае я обнаружил, что мы не можем использовать transform: translateX () перед transform: translateY (). если мы хотим использовать оба, мы должны использовать transform: translate (,).


-1

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

#element_with_transform {
  -webkit-transform: none;
  transform: none;
}

1
Это, вроде бы, действительно в названии вопроса
Евгений Панков

@EugenePankov Не вижу «никто» в названии. Именно это и решило мою проблему и вообще никто не предлагает выключить. Хотя это не точный ответ на этот вопрос, но он может помочь кому-то, кто не хочет использовать преобразование, и преобразование происходит из другой библиотеки. Так что я не хочу повышать голоса, но, пожалуйста, не отказывайтесь от голосования. Я отредактирую свой вопрос, чтобы сказать, что я не хочу голосовать "за".
Маккаси
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.