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?

iSenne
źródło
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 .

Kyle
źródło
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.

smfr
źródło
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');

    });
}  
Jayden Lawson
źródło
6

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

.fixed {
     position: sticky;
}
yckart
źródło
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.

defligra
źródło
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/

lowselfesteemsucks
źródło
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;}
abksharma
źródło
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.

Kerry Johnson
źródło
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

mrmadhat
źródło
0

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

.fixed_element {
   -webkit-transform: translateZ(0);
   position: fixed;
   ....
} 
Ron
źródło
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%);
}
Murf
źródło
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>
bortunac
źródło
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.

Adrian Adkison
źródło
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.

pan G.
źródło
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 (,).

Fahime Firoozpour
źródło
-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;
}
makkasi
źródło
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