ترفند CSS: اجرای transition از ارتفاع صفر تا auto
اگر به اندازه کافی با CSS کار کرده باشید به احتمال زیاد حداقل یک بار تلاش کرده اید که از transition برای height: 0
تا auto
استفاده کنید و میدانید که همچین چیزی امکان پذیر نیست و transition در این حالت کار نمیکند.
➡️ خوشبختانه، با ویژگی جدیدی که به برخی از مرورگرها اضافه شده در حال حاضر راه حلی برای این مشکل وجود دارد: این راهحل از CSS Grid استفاده می کند، بسیار آسان است و بی عیب و نقص کار می کند!
اجازه دهید با یک مثال عملی شروع کنیم، من این accordion ساده را ساخته ام:
ساختار HTML این accordion بسیار ساده است:
<div class="accordion">
<div class="accordion-title">Hover me!</div>
<div class="accordion-body">
<div>
<p>Lorem ipsum ...</p>
</div>
</div>
</div>
اگر با استفاده از ماوس بر روی accordion هاور کنید متوجه می شوید که یک dropdown ظاهر میشود، نمایش dropdown مشکلی ندارد اما خیلی سریع اتفاق میافتد، اگر بخواهیم dropdown بصورت smooth یا نرم ظاهر شود باید چه کاری انجام دهیم؟
در واقع در مثال قبلی تلاش کردم که با استفاده از transition بروی خاصیت height
کاری کنم که dropdown به نرمی ظاهر شود:
.accordion-body {
height: 0;
transition: 500ms height ease;
}
.accordion:hover .accordion-body {
height: auto;
}
❌ متاسفانه این روش کار نمیکند و همانطور که در ابتدای پست اشاره کردم انجام transition از height: 0
تا height: auto
با استفاده از CSS امکان پذیر نمیباشد.
اما چطور میشود این مشکل را حل کرد؟
اولین راهحل میتواند اختصاص عدد ثابت به جای مقدار auto
به خاصیت height
باشد.
این روش کار میکند اما بهترین راهحل ممکن نیست چون برای محاسبه این عدد ثابت باید از جاوا اسکریپت استفاده کنیم تا بتوانیم ارتفاع عنصر .accordion-body
را بدست بیاوریم اما راستش این هدفی نیست که دنبال میکردیم.
😕 آیا هنوز هم می توانیم با استفاده از CSS به این حالت دست پیدا کنیم؟
💡 در واقع بله، میتوانیم به جای height
از خاصیت max-height
استفاده کنیم:
.accordion-body {
max-height: 0;
transition: 500ms max-height ease;
}
.accordion:hover .accordion-body {
max-height: 200px;
}
نتیجه میشود:
از آنجایی که ما یک مقدار ثابت برای حداکثر ارتفاع یا max-height
تعریف می کنیم، مرورگر اکنون می تواند transition را به درستی انجام دهد.
😕 تنها مشکل اینجاست که با توجه به مقدار ثابتی که برای حداکثر ارتفاع تعریف می کنیم، اکنون ممکن است محتوا به ارتفاع بیشتری نیاز داشته باشد و به همین دلیل overflow شود.
اگر مطمئن هستید که محتوای شما همیشه به گونه ای خواهد بود که هرگز به ارتفاع خاصی نمی رسد پس استفاده از این روش بسیار خوب است! فقط از یک مقدار مناسب برای max-height
استفاده کنید.
با این حال، توجه داشته باشید هر چه مقدار max-height
بیشتر باشد transition عجیبتر میشود (سعی کنید max-height: 1000px
را در مثال قبلی قرار دهید تا ببینید چگونه اوضاع تغییر میکند)
🤔 آیا می توانیم بهتر عمل کنیم و بدون استفاده از height
/max-height
به نتیجه مطلوب برسیم؟
🎉 اینجاست که خاصیت CSS Grid به کمک ما می آید!
✅ در واقع ما میتوانیم از یک ترفند ساده استفاده کنیم که اساساً شامل ساخت یک CSS grid با یک grid item است.
تمام کاری که واقعاً باید انجام دهیم این است که برای grid-template-rows
یک transition از 0fr تا 1fr در نظر بگیریم، با این روش grid item ما از ارتفاع صفر تا ارتفاع طبیعیاش transition خواهد داشت. به همین سادگی:
.accordion-body {
display: grid;
grid-template-rows: 0fr;
transition: 250ms grid-template-rows ease;
}
.accordion:hover .accordion-body {
grid-template-rows: 1fr;
}
.accordion-body > div {
overflow: hidden;
}
این روش بسیار مناسب است. بدون ارتفاع ثابت، بدون روشهای عجیب، accordion ما همانطور که انتظار میرود کار می کند. واقعا فوق العاده است! 😄
فقط به این موضوع توجه کنید که در واقع شما نیاز دارید که مقدار overflow: hidden
را برای عنصر div که درون عنصر .accordion-body
قرار دارد در نظر بگیرید تا این روش به درستی کار کند؛ به نظر من این تغییر جزئی در CSS کاملاارزشش را دارد.
نکته ویژه
این روش به دلیل پشتیبانی خاصیت grid-template-rows
از انیمیشن قابل اجرا میباشد، در زمانی که این مقاله را می نویسم همه مرورگرهای اصلی از این ویژگی پشتیبانی می کنند، اما اگر می خواهید از این ویژگی استفاده کنید ابتدا سازگاری را بررسی کنید!
اگر از این صفحه بازدید کنید متوجه خواهید شد که این یک ویژگی کاملا جدید برای برخی از مرورگرها است و برای مثال از نسخه ۱۰۷ به مرورگر کروم اضافه شده است.