
بروزرسانی: 28 اردیبهشت 1404
انتقال ورودی های لایه بالایی و ویژگی نمایش در CSS-مجله Smashing
انیمیشن از و به display: none;
چیزی بود که ما فقط با JavaScript برای تغییر کلاس ها یا ایجاد هک های دیگر به آن می رسیدیم. دلیل اینکه ما نتوانستیم این کار را در CSS انجام دهیم ، در مشخصات جدید CSS Transions سطح 2 توضیح داده شده است:
وی گفت: "در سطح 1 این مشخصات ، انتقال فقط می تواند در طی یک رویداد تغییر سبک برای عناصری که دارای یک سبک قبل از تغییر هستند که توسط رویداد تغییر سبک قبلی ایجاد شده است ، شروع شود. این بدان معناست که انتقال نمی تواند بر روی عنصری آغاز شود که برای رویداد تغییر سبک قبلی ارائه نشده است. "
به عبارت ساده ، این بدان معنی است که ما نتوانستیم انتقال را بر روی یک عنصر پنهان شروع کنیم یا به تازگی ایجاد شده است.
چه می کند transition-behavior: allow-discrete
انجام دهید؟
allow-discrete
آیا نام عجیب و غریب برای ارزش خاصیت CSS است ، درست است؟ ما در مورد انتقال هستیم display: none
، پس چرا این نامگذاری نشده است transition-behavior: allow-display
در عوض؟ دلیل این امر این است که این کار کمی بیشتر از رسیدگی به CSS است display
املاک ، همانطور که سایر خصوصیات "گسسته" در CSS وجود دارد. یک قانون ساده این است که خصوصیات گسسته در حال انتقال نیست بلکه معمولاً بلافاصله بین دو حالت دور می شوند. نمونه های دیگر خصوصیات گسسته visibility
وت mix-blend-mode
بشر نمونه ای از این موارد را در پایان این مقاله درج می کنم.
برای خلاصه کردن ، تنظیم transition-behavior
دارایی به allow-discrete
به ما اجازه می دهد تا به مرورگر بگوییم که می تواند مقادیر یک خاصیت گسسته را عوض کند (به عنوان مثال ، display
با visibility
وت mix-blend-mode
) در 50 ٪ علامت به جای علامت 0 ٪ انتقال.
چه می کند @starting-style
انجام دهید؟
در @starting-style
قانون قبل از ارائه به صفحه ، سبک های یک عنصر را درست تعریف می کند. این در ترکیب با transition-behavior
و به همین دلیل است:
هنگامی که یک مورد به DOM اضافه می شود یا در ابتدا تنظیم می شود display: none
، به نوعی "شروع سبک" نیاز دارد که از آن نیاز به انتقال دارد. برای مثال بیشتر ، Popovers و عناصر گفتگو به یک لایه بالا اضافه می شوند که لایه ای است که خارج از جریان سند شما است ، می توانید به عنوان یک خواهر و برادر از آن نگاه کنید element in your page’s structure. Now, when opening this dialog or popover, they get created inside that top layer, so they don’t have any styles to start transitioning from, which is why we set
@starting-style
بشر نگران نباشید اگر همه اینها کمی گیج کننده به نظر می رسد. نسخه های نمایشی ممکن است آن را واضح تر جلوه دهند. نکته مهمی که باید بدانیم این است که ما می توانیم به مرورگر چیزی بدهیم که انیمیشن را با آن شروع کند زیرا در غیر این صورت چیزی برای تحریک از آن ندارد.
یادداشتی در مورد پشتیبانی مرورگر
در لحظه نوشتن ، transition-behavior
در Chrome ، Edge ، Safari و Firefox موجود است. این همان است @starting-style
، اما Firefox در حال حاضر از انیمیشن پشتیبانی نمی کند display: none
بشر اما به یاد داشته باشید که همه چیز در این مقاله می تواند کاملاً به عنوان یک پیشرفت مترقی مورد استفاده قرار گیرد.
اکنون که نظریه همه اینها را پشت سر خود داریم ، بیایید عملی شویم. من در این مقاله سه مورد استفاده را پوشش خواهم داد:
- انیمیشن از و به
display: none
در Dom. - دیالوگ های انیمیشن و پاپورها که از لایه بالایی وارد و خارج می شوند.
- "خواص گسسته" بیشتری می توانیم اداره کنیم.
انیمیشن از و به display: none
در DOM
برای مثال اول ، بیایید نگاهی بیندازیم @starting-style
تنها من این نسخه ی نمایشی را صرفاً برای توضیح جادو ایجاد کردم. تصور کنید که می خواهید دو دکمه در یک صفحه برای اضافه کردن یا حذف موارد لیست در داخل یک لیست بدون هماهنگ.
این می تواند HTML شروع شما باشد:
در مرحله بعد ، ما اقداماتی را اضافه می کنیم که موارد لیست را اضافه یا حذف می کنند. این می تواند هر روشی برای انتخاب شما باشد ، اما برای اهداف نمایشی ، من به سرعت کمی JavaScript را برای آن نوشتم:
document.addEventListener("DOMContentLoaded", () => { const addButton = document.querySelector(".btn-add"); const removeButton = document.querySelector(".btn-remove"); const list = document.querySelector(\'ul(role="list")\'); addButton.addEventListener("click", () => { const newItem = document.createElement("li"); list.appendChild(newItem); }); removeButton.addEventListener("click", () => { if (list.lastElementChild) { list.lastElementChild.classList.add("removing"); setTimeout(() => { list.removeChild(list.lastElementChild); }, 200); } });});
هنگام کلیک بر روی addButton
، یک مورد لیست خالی در داخل لیست بدون نظارت ایجاد می شود. هنگام کلیک بر روی removeButton
، آخرین مورد جدید است .removing
کلاس و سرانجام پس از 200 متر از DOM خارج می شود.
با این کار ، می توانیم برخی از CSS را برای موارد خود بنویسیم تا قسمت حذف را تحریک کنیم:
ul { li { transition: opacity 0.2s, transform 0.2s; &.removing { opacity: 0; transform: translate(0, 50%); } } }
این عالی است! ما .removing
انیمیشن در حال حاضر عالی به نظر می رسد ، اما آنچه ما در اینجا به دنبال آن بودیم ، راهی برای تحریک ورود مواردی بود که در داخل DOM ما وارد می شود. برای این کار ، ما باید آن سبک های شروع و همچنین وضعیت نهایی موارد لیست خود را تعریف کنیم.
ابتدا بیایید CSS را به روز کنیم تا حالت نهایی در داخل آن مورد لیست باشد:
ul { li { opacity: 1; transform: translate(0, 0); transition: opacity 0.2s, transform 0.2s; &.removing { opacity: 0; transform: translate(0, 50%); } } }
تغییر زیادی نکرده است ، اما اکنون این وظیفه ماست که به مرورگر اطلاع دهیم که سبک های شروع باید چه باشد. ما می توانیم این را به همان روشی که انجام دادیم تنظیم کنیم .removing
سبک هایی مانند این:
ul { li { opacity: 1; transform: translate(0, 0); transition: opacity 0.2s, transform 0.2s; @starting-style { opacity: 0; transform: translate(0, 50%); } &.removing { opacity: 0; transform: translate(0, 50%); } } }
اکنون ما به مرورگر اطلاع داده ایم که @starting-style
باید شامل کدورت صفر باشد و با استفاده از a کمی به پایین گره خورده باشد transform
بشر نتیجه نهایی چیزی شبیه به این است:
اما نیازی نیست که در آنجا متوقف شویم! ما می توانیم از انیمیشن های مختلف برای ورود و خروج استفاده کنیم. به عنوان مثال می توانیم سبک شروع خود را به موارد زیر بروز کنیم:
@starting-style { opacity: 0; transform: translate(0, -50%);}
با انجام این کار ، موارد از بالا وارد می شوند و از پایین خارج می شوند. مثال کامل را در این Codepen مشاهده کنید:
قلم (@@stary-sylede-up-in ، down-out (forked)) (https://codepen.io/smashingmag/pen/xjropgg) را توسط AltilityBend مشاهده کنید.
چه زمانی استفاده کنید transition-behavior: allow-discrete
در مثال قبلی مواردی را از DOM خود اضافه و حذف کردیم. در نسخه ی نمایشی بعدی ، ما موارد را با استفاده از CSS نشان می دهیم و پنهان می کنیم display
خاصیت راه اندازی اساسی تقریباً یکسان است ، به جز ما هشت مورد لیست را به DOM خود اضافه خواهیم کرد .hidden
کلاس متصل به آن:
یک بار دیگر ، برای اهداف نمایشی ، من کمی جاوا اسکریپت اضافه کردم که این بار ، .hidden
کلاس مورد بعدی هنگام کلیک بر روی addButton
و اضافه می کند hidden
کلاس هنگام کلیک بر روی removeButton
:
document.addEventListener("DOMContentLoaded", () => { const addButton = document.querySelector(".btn-add"); const removeButton = document.querySelector(".btn-remove"); const listItems = document.querySelectorAll(\'ul(role="list") li\'); let activeCount = 0; addButton.addEventListener("click", () => { if (activeCount < listItems.length) { listItems(activeCount).classList.remove("hidden"); activeCount++; } }); removeButton.addEventListener("click", () => { if (activeCount > 0) { activeCount--; listItems(activeCount).classList.add("hidden"); } });});
بیایید همه چیزهایی را که تاکنون آموخته ایم جمع کنیم ، اضافه کنیم @starting-style
به موارد ما ، و تنظیم اولیه را در CSS انجام دهید:
ul { li { display: block; opacity: 1; transform: translate(0, 0); transition: opacity 0.2s, transform 0.2s; @starting-style { opacity: 0; transform: translate(0, -50%); } &.hidden { display: none; opacity: 0; transform: translate(0, 50%); } } }
این بار ، ما اضافه کرده ایم .hidden
کلاس ، آن را تنظیم کنید display: none
، و همان را اضافه کرد opacity
وت transform
اعلامیه هایی که قبلاً با .removing
کلاس در آخرین مثال. همانطور که ممکن است انتظار داشته باشید ، ما برای موارد خود یک محو شدن خوب می گیریم ، اما حذف آنها هنوز هم ناگهانی است زیرا موارد خود را مستقیماً تنظیم می کنیم display: none
بشر
اینجاست transition-behavior
ملک بازی می شود. برای شکستن آن کمی بیشتر ، بیایید آن را حذف کنیم transition
ملک CSS قبلی ما و کمی آن را باز کنید:
ul { li { display: block; opacity: 1; transform: translate(0, 0); transition-property: opacity, transform; transition-duration: 0.2s; } }
تمام کاری که باید انجام شود انتقال است display
دارایی و تنظیم transition-behavior
دارایی به allow-discrete
:
ul { li { display: block; opacity: 1; transform: translate(0, 0); transition-property: opacity, transform, display; transition-duration: 0.2s; transition-behavior: allow-discrete; /* etc. */ } }
ما اکنون عنصر را از display: none
، و نتیجه دقیقاً همانطور که ما می خواستیم:
ما می توانیم از transition
خاصیت Shorthand برای ساختن کد ما کمی کمرنگ:
transition: opacity 0.2s, transform 0.2s, display 0.2s allow-discrete;
می توانید اضافه کنید allow-discrete
در آنجا اما اگر این کار را کردید ، توجه داشته باشید که اگر بعد از آن یک انتقال کوتاه را اعلام کردید transition-behavior
، آن را نادیده می گیرد. بنابراین ، به جای این:
transition-behavior: allow-discrete;transition: opacity 0.2s, transform 0.2s, display 0.2s;
... ما می خواهیم اعلام کنیم transition-behavior
پس از در transition
Shorthand:
transition: opacity 0.2s, transform 0.2s, display 0.2s;transition-behavior: allow-discrete;
در غیر این صورت ، transition
املاک Shorthand غلبه می کند transition-behavior
بشر
به قلم (@starty-Style و Transition-Behavior: اجازه-تخریب (چنگال)) مراجعه کنید (https://codepen.io/smashingmag/pen/ggkpxda) توسط AltilityBend.
دیالوگ های متحرک و پاپ ها وارد و خارج از لایه بالایی می شوند
بیایید چند مورد استفاده را با دیالوگ و پوپور اضافه کنیم. دیالوگ ها و پوپورها نمونه های خوبی هستند زیرا هنگام باز کردن آنها به لایه بالا اضافه می شوند.
آن لایه بالا چیست؟
ما قبلاً "لایه بالا" را به یک خواهر و برادر تشبیه کرده ایم element, but you might also think of it as a special layer that sits above everything else on a web page. It’s like a transparent sheet that you can place over a drawing. Anything you draw on that sheet will be visible on top of the original drawing.
The original drawing, in this example, is the DOM. This means that the top layer is out of the document flow, which provides us with a few benefits. For example, as I stated before, dialogs and popovers are added to this top layer, and that makes perfect sense because they should always be on top of everything else. No more z-index: 9999
!
اما این بیش از این است:
z-index
بی ربط است: عناصر موجود در لایه بالا ، صرف نظر از آنها ، همیشه در بالا هستندz-index
ارزش- سلسله مراتب دام مهم نیست: موقعیت یک عنصر در DOM بر ترتیب انباشت آن در لایه بالا تأثیر نمی گذارد.
- پس زمینه: ما به یک جدید دسترسی پیدا می کنیم
::backdrop
شبه عنصر که به ما امکان می دهد منطقه بین لایه بالایی و DOM را در زیر آن سبک کنیم.
امیدوارم که شما شروع به درک اهمیت لایه بالا و چگونگی انتقال عناصر در داخل و خارج از آن کنیم ، همانطور که با Popovers و Dialogues انجام می دهیم.
انتقال عنصر گفتگو در لایه بالا
HTML زیر حاوی دکمه ای است که باز می شود عنصر ، و آن
عنصر حاوی دکمه دیگری است که بسته می شود
بشر بنابراین ، ما یک دکمه داریم که باز می شود
و یکی که آن را می بندد.
اتفاقات زیادی در HTML با دستورات Invoker اتفاق می افتد که مرحله زیر را کمی آسان تر می کند ، اما در حال حاضر ، بیایید کمی JavaScript را اضافه کنیم تا این معین در واقع کار کند:
// Get all open dialog buttons.const openButtons = document.querySelectorAll(".open-dialog");// Get all close dialog buttons.const closeButtons = document.querySelectorAll(".close-dialog");// Add click event listeners to open buttons.openButtons.forEach((button) =< { button.addEventListener("click", () =< { const targetId = button.getAttribute("data-target"); const dialog = document.getElementById(targetId); if (dialog) { dialog.showModal(); } });});// Add click event listeners to close buttons.closeButtons.forEach((button) =< { button.addEventListener("click", () =< { const targetId = button.getAttribute("data-target"); const dialog = document.getElementById(targetId); if (dialog) { dialog.close(); } });});
من از سبک های زیر به عنوان نقطه شروع استفاده می کنم. توجه کنید که چگونه یک ظاهر طراحی می کنم ::backdrop
به عنوان یک امتیاز اضافی!
dialog { padding: 30px; width: 100%; max-width: 600px; background: #fff; border-radius: 8px; border: 0; box-shadow: rgba(0, 0, 0, 0.3) 0px 19px 38px, rgba(0, 0, 0, 0.22) 0px 15px 12px; &::backdrop { background-image: linear-gradient( 45deg in oklab, oklch(80% 0.4 222) 0%, oklch(35% 0.5 313) 100% ); }}
این منجر به انتقال بسیار سخت برای ورود می شود ، به این معنی که خیلی صاف نیست:
بیایید انتقال را به این عنصر گفتگو و پس زمینه اضافه کنیم. من این بار کمی سریعتر می روم زیرا تا الان ، شما به احتمال زیاد این الگوی را می بینید و می دانید چه اتفاقی می افتد:
dialog { opacity: 0; translate: 0 30%; transition-property: opacity, translate, display; transition-duration: 0.8s; transition-behavior: allow-discrete; &(open) { opacity: 1; translate: 0 0; @starting-style { opacity: 0; translate: 0 -30%; } }}
هنگامی که یک گفتگو باز است ، مرورگر سیلی می زند open
ویژگی در آن:
و این چیز دیگری است که می توانیم با CSS هدف قرار دهیم ، مانند dialog(open)
بشر بنابراین ، در این حالت ، ما باید تنظیم کنیم @starting-style
برای وقتی که گفتگو در یک است open
دولت
بیایید در حالی که در آن هستیم ، یک انتقال برای پس زمینه خود اضافه کنیم:
dialog { /* etc. */ &::backdrop { opacity: 0; transition-property: opacity; transition-duration: 1s; } &(open) { /* etc. */ &::backdrop { opacity: 0.8; @starting-style { opacity: 0; } } }}
حالا احتمالاً فکر می کنید: هه اما شما باید اضافه کنید display
خاصیت و transition-behavior: allow-discrete
در پس زمینه!
اما نه ، اینگونه نیست. حتی اگر من پس زمینه شبه خود را به CSS زیر تغییر دهم ، نتیجه همان باقی می ماند:
&::backdrop { opacity: 0; transition-property: opacity, display; transition-duration: 1s; transition-behavior: allow-discrete; }
معلوم است که ما با یک کار می کنیم ::backdrop
و هنگام کار با a ::backdrop
، ما به طور ضمنی با CSS نیز کار می کنیم overlay
ویژگی ، که مشخص می کند آیا عنصری که در لایه بالا ظاهر می شود در حال حاضر در لایه بالا ارائه شده است.
وت overlay
به همین ترتیب اتفاق می افتد که یکی دیگر از ویژگی های گسسته است که ما باید در آن بگنجانیم transition-property
اعلامیه:
dialog { /* etc. */&::backdrop { transition-property: opacity, display, overlay; /* etc. */}
متأسفانه ، این در حال حاضر فقط در مرورگرهای کروم پشتیبانی می شود ، اما می توان از آن به عنوان یک پیشرفت مترقی استفاده کرد.
و ، بله ، ما باید آن را به dialog
سبک ها نیز:
dialog { transition-property: opacity, translate, display, overlay; /* etc. */&::backdrop { transition-property: opacity, display, overlay; /* etc. */}
به قلم (گفتگوی: شروع سبک ، انتقال-behavior ، روکش (چنگال)) (https://codepen.io/smashingmag/pen/pvzqoge) را مشاهده کنید.
به جای گفتگو ، برای یک پوپور تقریباً یکسان است. من از همین تکنیک استفاده می کنم ، فقط این بار با Popovers کار می کنم:
قلم (انتقال Popover با @stary-Style (Forked)) (https://codepen.io/smashingmag/pen/emoblxe) را توسط AltilityBend مشاهده کنید.
سایر خصوصیات گسسته
علاوه بر مواردی که در اینجا پوشش داده ایم ، چند خاصیت گسسته دیگر نیز وجود دارد. اگر نسخه ی نمایشی دوم را به یاد دارید ، جایی که ما برخی از موارد را از و به آن منتقل کردیم display: none
، با همین visibility
در عوض خاصیت این می تواند برای مواردی که می خواهید مواردی را برای حفظ فضای جعبه عنصر حفظ کنید ، حتی اگر نامرئی باشد ، مفید باشد.
بنابراین ، در اینجا همان مثال ، فقط با استفاده از visibility
به جای display
بشر
قلم (انتقال خاصیت دید (Forked)) (https://codepen.io/smashingmag/pen/lepmjqx) را توسط AltilityBend مشاهده کنید.
CSS mix-blend-mode
ملک یکی دیگر از مواردی است که گسسته تلقی می شود. برای اینکه کاملاً صادقانه بگویم ، من نمی توانم یک مورد استفاده خوب برای نسخه ی نمایشی پیدا کنم. اما من جلوتر رفتم و نمونه ای از این دست را ایجاد کردم که در آن دو mix-blend-mode
S درست در وسط انتقال به جای فوراً تغییر دهید.
به قلم (https://codepen.io/smashingmag/pen/bnboxzp) به قلم (transitioning mix-mode (forked)) مراجعه کنید.
پیچیدن
این یک مرور کلی در مورد چگونگی انتقال عناصر به داخل و خارج از لایه بالا است! در یک دنیای ایده آل ، ما می توانیم بدون نیاز به یک ملک کاملاً جدید مانند transition-behavior
فقط برای انتقال در غیر این صورت خواص "غیرقابل انتقال" ، اما ما در اینجا هستیم و خوشحالم که آن را داریم.
اما ما نیز باید در مورد آن بیاموزیم @starting-style
و اینکه چگونه مجموعه ای از سبک ها را به مرورگرها ارائه می دهد که می توانیم برای شروع یک انتقال برای عنصری که در لایه بالایی قرار دارد ، استفاده کنیم. در غیر این صورت ، این عنصر هیچ چیزی برای انتقال از ابتدا ارائه نمی دهد ، و ما هیچ راهی برای انتقال آنها به راحتی در داخل و خارج از لایه بالا نداریم.

منبع: https://smashingmagazine.com/2025/01/transitioning-top-layer-entries-display-property-css/