'transform3d' tidak bekerja dengan posisi: anak tetap

142

Saya memiliki situasi di mana, dalam keadaan CSS normal, div tetap akan diposisikan tepat di tempat yang ditentukan ( top:0px, left:0px).

Ini tampaknya tidak dihargai jika saya memiliki orang tua yang memiliki transformasi translate3d. Apakah saya tidak melihat sesuatu? Saya telah mencoba webkit lain seperti gaya dan mengubah opsi asal tetapi tidak berhasil.

Saya telah melampirkan JSFiddle dengan contoh di mana saya mengharapkan kotak kuning berada di sudut atas halaman daripada di dalam elemen kontainer.

Anda dapat menemukan di bawah versi biola yang disederhanakan:

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

Bagaimana cara membuat translate3d berfungsi dengan anak-anak dengan posisi tetap?

Juan Carlos Moreno
sumber
Masalah yang sama juga terjadi dengan filter: stackoverflow.com/q/52937708/8620333
Temani Afif

Jawaban:

200

Ini karena transformmembuat sistem koordinat lokal baru, sesuai spesifikasi W3C :

Dalam namespace HTML, nilai apa pun selain nonehasil transformasi dalam pembuatan konteks bertumpuk dan blok yang memuat. Objek bertindak sebagai blok penampung untuk turunan yang diposisikan tetap.

Artinya, pemosisian tetap menjadi tetap ke elemen yang diubah, bukan area pandang.

Saat ini tidak ada solusi yang saya sadari.

Hal ini juga didokumentasikan di artikel Eric Meyer: Un-fixing Fixed Elements with CSS Transforms .

saml
sumber
Terima kasih, saya tidak memperhatikan bahwa spesifikasi sebenarnya memiliki info itu ..... Saya kira saya mendapat jawaban yang setara dengan matematika: "menurut definisi" :)
Juan Carlos Moreno
3
@INT, saya rasa tidak akan ada solusi untuk ini. Ada kasus penggunaan utama untuk tidak mengizinkan solusi: input yang diberikan pengguna berpotensi mencakup kontrol di luar area yang ditentukan (pikirkan opsi penambahan email berbahaya ke toolbar gmail). Solusi terbaik adalah untuk menghindari perubahan untuk saat ini jika Anda akan menggunakan fixed dari dalamnya.
saml
1
Bukankah menyetel atribut atas CSS ke window.scrollHeight apa pun yang berhasil? Anda mungkin harus benar-benar memposisikannya juga, tetapi sesuatu seperti ini seharusnya bisa dilakukan, bukan? (terlalu malas untuk benar-benar menguji sekarang)
Brad Orego
@bradorego Anda benar, saya baru saja menambahkan kode yang saya gunakan.
UzumakiDev
Sejauh yang saya tahu, ini masih berubah dalam spesifikasi. Lihat Bug 16328 - Penggunaan "blok yang mengandung" tidak cocok dengan definisi CSS2.1 .
tiga
13

Saya mengalami kedipan pada navigasi atas tetap saya ketika item di halaman menggunakan transformasi, hal berikut ini diterapkan pada navigasi teratas saya menyelesaikan masalah melompat / berkedip:

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

Berkat jawaban ini di SO

merampok
sumber
12

Seperti yang disarankan Bradoergo, dapatkan jendela scrollTopdan tambahkan ke posisi absolut atas seperti:

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

Ini berhasil untuk saya.

UzumakiDev
sumber
3
Berhasil! tetapi alih-alih mengikat ke "jendela", saya harus mengikat ke div yang sedang bergulir. Juga, elemen tetap berkedip.
melatih
Apa yang harus dilakukan jQuery di sini?
FlorianB
Ini bisa saja berhasil, tetapi seperti @train yang disebutkan, itu berkedip.
Etienne Dupuis
Ya, pembaruan ini tidak cukup cepat agar cukup bersih untuk penggunaan saya: - / ide bagus tho
reid
Ini adalah praktik yang sangat buruk, jangan lakukan perubahan gaya dengan js
Wannes
5

Di Firefox dan Safari Anda dapat menggunakan position: sticky;bukannya position: fixed;tapi itu tidak akan bekerja di browser lain. Untuk itu Anda membutuhkan javascript.

Dušan
sumber
2
Sticky positioning adalah gabungan dari pemosisian relatif dan tetap, dan ini benar-benar eksperimental , saya sangat menyarankan untuk menghindari ini, karena ini belum standar.
Farside
1
AFAIK di Firefox dan Safari dapat Anda gunakan dengan mudah position:fixeddan akan tetap berfungsi seperti yang diharapkan.
oriadam
@oriadam tidak, saya memiliki masalah ketika orang tua menggunakan translate3d dan posisi tetap anak-anak terbang di sekitar dalam beberapa kasus. Akan mencoba menggunakan stickysaat itu 'sudah didukung oleh browser utama: caniuse.com/#feat=css-sticky
Lukas Liesis
stickymungkin solusinya, ini berfungsi di browser modern.
aboutqx
3

Menurut pendapat saya, metode terbaik untuk mengatasi ini adalah dengan menerapkan terjemahan yang sama, tetapi hancurkan anak-anak yang perlu diperbaiki dari elemen induknya (diterjemahkan); lalu terapkan terjemahan ke div di dalam position: fixedpembungkus.

Hasilnya terlihat seperti ini (dalam kasus Anda):

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

Meskipun ini mungkin tidak ideal untuk beberapa kasus penggunaan, biasanya jika Anda memperbaiki div, Anda mungkin tidak terlalu peduli tentang elemen apa yang menjadi induknya / di mana ia berada di pohon warisan di DOM Anda, dan tampaknya menyelesaikan sebagian besar masalah - sambil tetap membiarkan keduanya translatedan position: fixedhidup dalam harmoni (relatif).

reid
sumber
0

Saya mengalami masalah yang sama. Satu-satunya perbedaan adalah bahwa elemen saya dengan 'position: fixed' memiliki properti gaya 'top' dan 'left' yang disetel dari JS. Jadi saya bisa menerapkan perbaikan:

var oRect = oElement.getBoundingClientRect();

Objek oRect akan berisi koordinat kiri dan atas yang nyata (relatif terhadap port tampilan). Jadi, Anda dapat menyesuaikan properti oElement.style.top dan oElement.style.left Anda yang sebenarnya.

Mike Dobrin
sumber
Ini berfungsi di IE dan Chrome, tetapi tidak di browser standar Android. Kiri adalah angka tetapi selalu ditarik pada posisi 0
Adaptabi
0

Saya memiliki sidebar di luar kanvas yang menggunakan -webkit-transform: translate3d. Ini mencegah saya menempatkan footer tetap di halaman. Saya menyelesaikan masalah dengan menargetkan kelas pada halaman html yang ditambahkan ke tag pada inisialisasi sidebar dan kemudian menulis css: not qualifier untuk menyatakan "-webkit-transform: none;" ke tag html ketika kelas itu tidak ada di tag html. Semoga ini membantu seseorang di luar sana dengan masalah yang sama ini!

WeisbergWeb
sumber
0

Coba terapkan transformasi berlawanan ke elemen anak:

<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>
Mari Do
sumber
0

Tambahkan kelas dinamis saat elemen bertransformasi. $('#elementId').addClass('transformed'). Lalu lanjutkan dengan mendeklarasikan di 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 
}

kemudian

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

kemudian

.transformed {
    #elementId { 
        .translate3d(0px, 20px, 0px);
    }
}

Sekarang position: fixedketika diberikan nilai properti topdan z-indexpada elemen anak hanya berfungsi dengan baik dan tetap diperbaiki sampai elemen induk berubah. Saat transformasi dikembalikan, elemen turunan akan muncul sebagai diperbaiki lagi. Ini akan memudahkan situasi jika Anda benar-benar menggunakan bilah sisi navigasi yang membuka dan menutup dengan sekali klik, dan Anda memiliki tab-set yang harus tetap melekat saat Anda menggulir ke bawah halaman.

mr.G.
sumber
-1

Salah satu cara untuk mengatasinya adalah dengan menerapkan transformasi yang sama ke elemen tetap:

<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>
fgassert.dll
sumber
1
Pada bug IE tidak ada di tempat pertama
oriadam