Naprawione pozycje nie działają podczas korzystania z -webkit-transform


155

Używam -webkit-transform (i -moz-transform / -o-transform), aby obrócić element div. Dodano również ustaloną pozycję, aby div był przewijany razem z użytkownikiem.

W Firefoksie działa dobrze, ale w przeglądarkach opartych na webkitach jest zepsuty. Po użyciu -webkit-transform, ustalona pozycja już nie działa! Jak to możliwe?


4
Strona demonstracyjna często pomaga ludziom odpowiadać na pytania - jsbin.com pozwala tworzyć tymczasowe strony ilustrujące problem, jeśli nie chcesz tworzyć linków do swojej witryny.
— Rich Bradshaw,

jsfiddle.net to kolejny dobry przykład tymczasowego kosza edycji.
— Kyle,

@Rich Bradshaw jsbin.com jest bardzo fajny. Nie wiedziałem tego aż do teraz. Większość moich projektów prowadzę lokalnie, więc następnym razem z nich skorzystam. Tnx
— iSenne

7
W ogóle nie działa dobrze w Firefoksie.
— vsync,

3
Nadal problem w 2017 r. Wygląda na to, że nadal trzymają się komunikatu „To funkcja, a nie błąd!” argument ...
— Max

Odpowiedzi:


87

Po pewnych badaniach w witrynie Chromium pojawił się raport o błędzie dotyczący tego problemu, jak dotąd przeglądarki Webkit nie mogą renderować tych dwóch efektów jednocześnie.

Sugerowałbym dodanie CSS tylko do Webkit do twojego arkusza stylów i przekształcenie przekształconego div w obraz i użycie go jako tła.

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

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

Więc na razie będziesz musiał to robić w staromodny sposób, dopóki przeglądarki Webkit nie dogonią FF.

EDYCJA: Od 24.10.2012 błąd nie został rozwiązany.


Wydaje się, że nie jest to błąd, ale aspekt specyfikacji ze względu na dwa efekty wymagające oddzielnych układów współrzędnych i kolejności układania. Jak wyjaśniono w tej odpowiedzi .


34
Jeszcze więcej lat później, nadal nie rozwiązany. Dość smutne.
— Amalgovinus

9
Zgodnie z tą odpowiedzią nie jest to błąd, ale część specyfikacji.
— MichaelRushton,

15
usiąść i obserwować - Założę się, że będzie żyć do jego 10-lecia
— lzl124631x

29
30 sierpnia 2017, dziennik kapitański. Napotkaliśmy także dziwną anomalię, którą tak dawno opisali inni kapitanowie. Rozwiązanie wciąż nie zostało wdrożone.
— Luoruize

14
To jest błąd, przed którym ostrzegał mnie ojciec mojego ojca.
— danjones_mcr

96

Specyfikacja CSS Transforms wyjaśnia to zachowanie. Elementy z transformacjami działają jak blok zawierający elementy potomne o ustalonej pozycji, więc position: fixed pod czymś z transformacją nie ma już stałego zachowania.

Działają po zastosowaniu do tego samego elementu; element zostanie ustawiony jako stały, a następnie przekształcony.


9
To jedyna pomocna i poprawna odpowiedź. Przestań tłumaczyć element nadrzędny i przetłumaczyć elementy podrzędne, w których element stały jest jego częścią. Oto moje skrzypce: JSFIDDLE
— Falk

2
a co jeśli chcę również przekształcić stały element?
— Marc

7

Dla każdego, kto stwierdzi, że ich obrazy tła znikają w Chrome z powodu tego samego problemu z załączaniem w tle: naprawiono; - to było moje rozwiązanie:

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

Coś (trochę zepsuty), które zadziałało dla mnie, to position:stickyzamiast tego:

.fixed {
     position: sticky;
}

5
aktualizacje.html5rocks.com/2012/08/ ... a tak ... ale wygląda na to, że nie jest dobrze obsługiwany
— coiso

1
lepki jest inny. Główny problem polega na tym, że w przypadku fixed chcemy zignorować pozycję kontenera (bardzo przydatne np. W animacjach krycia). Nie mogę uwierzyć, że ten błąd nadal istnieje po latach. Okropny.
— FlorianB,

6

Sierpień 2016 i naprawiona pozycja i animacja / transformacja nadal stanowią problem. Jedynym rozwiązaniem, które mi się sprawdziło - było stworzenie animacji dla elementu podrzędnego, która zajmuje więcej czasu.


Proszę o odpowiedź na nowe pytania. Te pytania potrzebują Ciebie bardziej niż osoby, która zadała pytanie w 2010 roku. Pewnie już rozwiązały problem, nie sądzisz? Również to pytanie ma już zaakceptowaną odpowiedź.
— Umair Farooq

5
Nie! Wciąż jest problem ... osoba, która zadała pytanie, mogła znaleźć inne rozwiązanie - ale nie bez powodu znalazłem ten wątek.
— defligra

Jak sobie życzysz. Zostawiłem ten komentarz, przeglądając pierwsze pytania ludzi. A ponieważ dołączyłeś właśnie dzisiaj i była to Twoja pierwsza odpowiedź, a także późna odpowiedź, dlatego zostawiłem ten komentarz. Nie głosowałem przeciw. To dla ciebie dobra szansa.
— Umair Farooq,

1
@UmairFarooq może zadać kolejne pytanie, ponieważ mogłoby zostać oznaczone jako duplikat. Przyszedłem tutaj tylko z wyszukiwaniem w Google i uznałem to pytanie za przydatne, odpowiedź defligra też.
— koMah

3

Właściwie znalazłem inny sposób naprawienia tego „błędu”:

Mam element kontenera, który zawiera stronę z animacjami css3. Gdy strona zakończyła animację, właściwość css3 ma wartość: transform: translate (0,0) ;. Właśnie usunąłem tę linię i wszystko działało tak, jak powinno - pozycja: naprawiona wyświetla się poprawnie. Kiedy do tłumaczenia strony jest stosowana klasa css, dodawana jest właściwość translate i działała również animacja css3.

Przykład:

.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);    
 }

Demo: http://jsfiddle.net/ZWcD9/


1
Dla mnie był to fakt posiadania tych stylów na opakowaniu zawierającym stały element, który uniemożliwiał sklejanie się tego naprawionego: -webkit-perspektywa: 1000; -webkit-transform-style: preserve-3d; Zdjąłem te i wszystko działa dobrze. To i tak były wątpliwe optymalizacje!
— Amalgovinus

Usunięcie transformacji w jakikolwiek sposób jest prawdopodobnie najlepszym jak dotąd obejściem. Coś w rodzaju zanikania, po zakończeniu, powinno być możliwe do usunięcia bez wpływu na wygląd elementu. Właściwie nie jestem pewien, jak kręcenie się transformX (0) wpłynęłoby na wydajność renderowania, jeśli w ogóle cokolwiek; może zostać zignorowane, może zaszkodzić wydajności lub poprawić ją, wymuszając jakieś przyspieszenie 3D. Kto wie. W każdym razie, po zakończeniu animacji lub nawet tuż przed dodaniem do niej stałego elementu, można po prostu usunąć klasy CSS z transformacji.
— Triynko

1

w moim projekcie phonegap webkit transform -webkit-transform: translateZ (0); działał jak urok. To już działało w Chrome i Safari, ale nie w przeglądarce mobilnej. może być też jeszcze jeden problem, w niektórych przypadkach WRAPPER DIV nie są ukończone. stosujemy czystą klasę w przypadku pływających DIV.

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

1

Prawdopodobnie z powodu błędu w Chrome, ponieważ nie mogę replikować w Safari ani Firefox, ale działa to w Chrome 40.0.2214.111 http://jsbin.com/hacame/1/edit?html,css,output

Jest to bardzo szczególna struktura, więc w żadnym wypadku nie jest to uniwersalna poprawka CSS w jednym wierszu, ale być może ktoś może przy niej majstrować, aby działała w Safari i Firefox.


1

Miałem ten problem, próbując zaimplementować reakcję kolorów z widokami reagowania na przesuwanie (rsw). Problem dla mnie polegał na tym, że rsw dotyczy translate(-100%, 0)panelu zakładek, który przerywa domyślny element div o stałej pozycji dodany na pełnym ekranie, który po kliknięciu zamyka model próbnika kolorów.

Dla mnie rozwiązaniem było zastosowanie odwrotnej transformacji do stałego elementu (w tym przypadku translate(100%, 0)rozwiązało to mój problem. Nie jestem pewien, czy jest to przydatne w innych przypadkach, ale pomyślałem, że i tak się podzielę).

Oto przykład pokazujący to, co opisałem powyżej:

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


0

Dodanie -webkit-transformdo stałego elementu rozwiązało problem.

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

20
To mi się nie udało. Czy jesteś w stanie stworzyć demo tego działania?
— Alex

4
To rozwiązało problem w Chrome, FWIW. Dzięki Ron.
— Chris

3
Dziękuję, to rozwiązało problem. Uratował mi życie!
— styke

1
@Neil Monroe, Android 2.3 to zupełnie nowa historia. W ogóle nie obsługuje stałego pozycjonowania :)
— Wiseman

8
Oto Fiddle, w którym używanie translateZ(0) NIE działa. To prawda, że ​​czasami działa, widziałem sytuacje, w których działało. Ale nadal nie mogę tego zawęzić.
— Zequez,

0

Oto, co działa dla mnie na wszystkich przetestowanych przeglądarkach i urządzeniach mobilnych (Chrome, IE, Firefox, Safari, iPad, iPhone 5 i 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
Dlaczego głosy przeciw? Byłoby miło, gdybyś skomentował, dlaczego przegłosowałeś moją odpowiedź?
— Murf

0

ustalona pozycja elementu jest zepsuta, jeśli zastosujesz transformację do dowolnego przodka.

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

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

0

Jeśli możesz użyć javascript jako opcji, może to być obejściem w celu umieszczenia elementu o ustalonej pozycji względem okna, gdy znajduje się on wewnątrz przekształconego elementu:

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

To prawda, że ​​będziesz musiał również dostosować wysokość i szerokość, ponieważ fixedElbędziesz obliczać to na podstawie kontenera. To zależy od twojego przypadku użycia, ale pozwoli ci to przewidzieć ustalenie pozycji czegoś, niezależnie od tego, jaki jest to kontener.


0

Dodaj klasę dynamiczną podczas transformacji elementu. $('#elementId').addClass('transformed'). Następnie zadeklaruj w css,

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

następnie

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

następnie

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

Now position: fixed, gdy podano wartości właściwości top i z-index w elemencie podrzędnym, po prostu działa dobrze i pozostaje niezmienne do momentu transformacji elementu nadrzędnego. Kiedy transformacja zostanie cofnięta, element potomny wyskakuje jako naprawiony ponownie. Powinno to złagodzić sytuację, jeśli faktycznie używasz bocznego paska nawigacji, który otwiera się i zamyka po kliknięciu, a masz zestaw zakładek, który powinien pozostać lepki podczas przewijania strony.


0

w moim przypadku okazało się, że nie możemy użyć transform: translateX () przed transform: translateY (). jeśli chcemy użyć obu, powinniśmy użyć transform: translate (,).


-1

Proszę nie głosować, ponieważ nie jest to dokładna odpowiedź, ale może komuś pomóc, ponieważ jest to szybki sposób na wyłączenie transformacji. Jeśli naprawdę nie potrzebujesz transformacji rodzica i chcesz, aby Twoja stała pozycja znów działała:

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

1
To jest tak naprawdę w tytule pytania
— Eugene Pankov,

@EugenePankov Nie widzę „none” w tytule. To właśnie rozwiązało mój problem i generalnie nikt nie sugeruje, aby go wyłączyć. Chociaż nie jest to dokładna odpowiedź na to pytanie, może pomóc komuś, kto nie chce używać transformacji, a transformacja pochodzi z innej biblioteki. Więc nie chcę głosów w górę, ale proszę nie głosować w dół. Zmienię moje pytanie, aby powiedzieć, że nie chcę głosować za.
— makkasi
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.