Rumah > Artikel > hujung hadapan web > getComputedStyle: Bahagian yang baik, buruk dan hodoh
getComputedStyle adalah satu daripada jenis. Ia melakukan beberapa perkara menarik di latar belakang dan mempunyai cara penggunaannya yang unik. Dalam siaran ini saya akan berkongsi pengalaman dan pemikiran saya tentang API pahit manis ini.
Saya mengharapkan diri saya untuk mengedit siaran ini kerana saya sering berinteraksi dengan fungsi ini pada masa kini. Saya juga fikir terdapat banyak kes khusus untuknya juga. Dengan cara ini saya akan meletakkan beberapa pautan yang membantu saya dalam perjalanan saya di penghujung siaran.
Terus dari MDN:
Kaedah Window.getComputedStyle() mengembalikan objek yang mengandungi nilai semua sifat CSS sesuatu elemen, selepas menggunakan lembaran gaya aktif dan menyelesaikan sebarang pengiraan asas yang mungkin mengandungi nilai tersebut.
Nilai sifat CSS individu diakses melalui API yang disediakan oleh objek atau dengan mengindeks dengan nama sifat CSS.
Contoh penggunaan dalam JavaScript biasa:
const element = document.getElementById("#box"); // Get the computed styles of an element const styles = getComputedStyle(element);
Ringkasnya, ia mengembalikan gaya untuk elemen yang diberikan. Sedikit yang menarik di sini ialah menyelesaikan pengiraan. Katakan anda telah memberikan sifat lebar dalam CSS dengan calc():
#box { width: calc(100px - 80px); }
Ia akan memberi anda 20px sebagai hasilnya. Bermakna anda sebenarnya boleh mengakses hasil pengiraan CSS daripada JavaScript. Ia juga mengira ruang pandang dan unit peratusan (100vj, 50% dsb.) dan memberikan hasil dalam piksel. Hebat!
GOTCHA: Nilai yang dikira bergantung pada sifat dan ia bukan statik. Bermakna anda tidak boleh mengharapkan ia mengira sesuatu seperti ini:
#box { --box-width: calc(100px - 80px); width: var(--box-width); }
// boxWidth variable will be set to string `calc(100px - 80px)` // Not `20px` const boxWidth = getComputedStyle(element)["--box-width"];
Ini benar-benar masuk akal kerana adalah mustahil untuk mengira hasil pembolehubah CSS secara statik. Ia bergantung pada persekitaran dan aspek harta benda (Fikirkan peratusan sebagai contoh).
Walau bagaimanapun, anda akan mempunyai 20 piksel jika anda cuba mengakses sifat lebar. Ia akhirnya akan mengira lebar untuk elemen tertentu:
// 20px const { width } = getComputedStyle(element);
Itu bagus dan semua kecuali apakah kes penggunaan sebenar?
Jika anda membaca siaran ini selepas calc-size() tersedia secara meluas pada penyemak imbas moden, berhenti dan gunakannya. Ia berkemungkinan akan mengatasi prestasi penyelesaian kami di sini. Jika anda terperangkap dalam realiti di mana kita tidak boleh beralih kepada auto, teruskan!
Dalam perjalanan pembangunan web anda, anda mungkin pernah mengalami beberapa kali menganimasikan ke/dari auto. Perpustakaan animasi mungkin sesuai di sini tetapi bagaimana jika saya beritahu anda tidak memerlukannya sama sekali?
Katakan ada kotak yang boleh kita togol hidup/mati yang mempunyai beberapa kandungan teks. Kandungan teks akan menjadi dinamik jadi kami tidak boleh memberikannya ketinggian maksimum terlebih dahulu. Oh pereka juga mahukan animasi di sana, ia mesti transit dari 0px ke ketinggian auto perlahan-lahan.
Yang berikut ialah HTML dan CSS kami:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> </head> <style> #box { position: relative; display: block; width: fit-content; height: 0px; overflow: hidden; background-color: rebeccapurple; color: whitesmoke; transition: 1s; } </style> <body> <button type="button" id="toggle">toggle</button> <div id="box"></div> <script type="module" src="/src/main.ts" defer></script> </body> </html>
Dalam bahagian skrip, kami tidak akan berbuat banyak untuk permulaan. Kami hanya perlu mengekalkan keadaan mudah untuk meletakkan atau mengalih keluar kandungan teks. (Sama ada atau tidak menggunakan TS terpulang kepada anda):
// get the wrapper div const box = document.getElementById("box") as HTMLDivElement; // get the trigger button const button = document.getElementById("toggle") as HTMLButtonElement; // state that keeps track let toggle = false; function changeBoxContent() { if (toggle) { box.innerText = `Lorem ipsum dolor sit, amet consectetur adipisicing elit. Minima culpa ipsum quibusdam quia dolorum excepturi sequi non optio, ad eaque? Temporibus natus eveniet provident sit cum harum, praesentium et esse?`; } else { box.innerText = ""; } } button.addEventListener("click", () => { // flip the toggle toggle = !toggle; // update the content changeBoxContent(); // ... });
Kod di sini hanya menetapkan innerTeks kotak kepada beberapa rentetan psudo atau mengembalikannya semula kepada rentetan kosong.
Jika anda mengklik butang sekarang, anda akan melihat tiada apa yang berubah. Ini kerana kami menetapkan ketinggian kotak kepada 0 piksel dan menyembunyikannya sebagai limpahan.
Untuk mengetahui berapa banyak ruang yang kami perlukan untuk teks, kami boleh menetapkan ketinggian kotak kepada auto dan memanggil getComputedStyle pada kotak kami. Idea di sini adalah untuk membiarkan elemen membesar seberapa banyak yang diperlukan melalui auto dan getComputedStyle di sini akan membawa kita saiz itu dalam piksel.
button.addEventListener("click", () => { // flip the toggle toggle = !toggle; // update the content changeBoxContent(); // set the element's height to `auto`, this enlarges the element to fit it's content box.style.height = "auto"; // we got our desired height property! const height = getComputedStyle(box).height; console.log(height); });
Anda sepatutnya melihat kotak mempunyai ketinggian yang sama seperti yang diperlukan apabila anda mengklik butang. Kita juga boleh melihat ketinggian dalam piksel dalam konsol:
Itu bagus tetapi kami tidak pasti akan beralih.
Oleh kerana kita tahu ketinggian yang kita perlukan, mungkin kita boleh menetapkan ketinggian kotak kembali ke tempatnya. Dalam panggilan ke requestAnimationFrame, kita boleh menetapkannya kepada ketinggian yang kita ada daripada getComputedStyle. Jom cuba!
button.addEventListener("click", () => { // flip the toggle toggle = !toggle; // update the content changeBoxContent(); // set the element's height to `auto`, this enlarges the element to fit it's content box.style.height = "auto"; // we got our desired height property! const height = getComputedStyle(box).height; // set the height back to where it was (0px) box.style.height = ""; // set the final height in next animation frame requestAnimationFrame(() => { box.style.height = height; }); });
Memandangkan kita tahu tetapkan ketinggian kepada 0px dan ubahnya dalam bingkai animasi seterusnya kita sepatutnya melihatnya menganimasikan, bukan?
Nah, tidak betul-betul. Jika anda menjalankan ini dalam Chrome dalam PC mewah, anda harus memerhati animasi peralihan TETAPI dalam PC hujung bawah atau dalam sesetengah penyemak imbas (seperti Firefox), anda boleh melihat tiada apa yang berubah.
Perbandingan Firefox dan Chrome pada komputer saya:
Sebab mengapa ini berlaku adalah kerana pengiraan untuk reka letak berlaku selepas gaya. Kami tidak dapat menjamin pengiraan susun atur kami akan berlaku sebelum pengiraan gaya. Juga pelayar mempunyai pelaksanaan requestAnimationFrame yang berbeza juga, nampaknya. (Anda boleh mengetahui lebih lanjut mengenainya di sini)
Don't get into despair though! We have multiple solutions for this. We can:
Let's try forcing the browser to calculate styles first. Remember getComputedStyle? I'm sure you do. It'll come to our rescue here too!
Right after we set height back to 0px, we'll force to recalculate the layout:
button.addEventListener("click", () => { // flip the toggle toggle = !toggle; // update the content changeBoxContent(); // set the element's height to `auto`, this enlarges the element to fit it's content box.style.height = "auto"; // we got our desired height property! const height = getComputedStyle(box).height; // set the height back to where it was (reset) box.style.height = ""; // we're synchronously forcing the browser to recalculate the height of the element getComputedStyle(box).height; // set the final height in next animation frame requestAnimationFrame(() => { box.style.height = height; }); });
GOTCHA: You might be thinking why we're accessing height property but not assigning it to anything. Well that's because getComputedStyle computes a property on access. It's actually to make it more optimized, it'll only run layout calculations on access to top, left, bottom, right, width and height. Its not documented but good to keep in mind. Try changing it to getComputedStyle(box), you'll see nothing has changed.
So that was one way to solve it and honestly I like this way much better. It's good to know double rAF() trick too, though.
For that we simply need to wrap our requestAnimationFrame with another requestAnimationFrame:
button.addEventListener("click", () => { // flip the toggle toggle = !toggle; // update the content changeBoxContent(); // set the element's height to `auto`, this enlarges the element to fit it's content box.style.height = "auto"; // we got our desired height property! const height = getComputedStyle(box).height; // set the height back to where it was (reset) box.style.height = ""; // set the final height in next animation frame requestAnimationFrame(() => { requestAnimationFrame(() => { box.style.height = height; }); }); });
Think of it like in the next frame, we've queued an animation that'll run on the next frame. I know it sounds weird but that used to solve lots of problems since it has a bug in Chrome too.
That's the wrap! As you can see in a modern world where we have WAAPI, transitions and getComputedStyle still have their use! It's a bit nasty to understand at start but it has it's own way of doing things, what can I say!
Sources:
Transition to Height Auto With Vue.js by Markus Oberlehner
Need cheap paint? Use getComputedStyle().opacity by Webventures
Atas ialah kandungan terperinci getComputedStyle: Bahagian yang baik, buruk dan hodoh. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!