یک مرور کلی اساسی در مورد نحوه ساخت کامپوننتهای <button> با قابلیت تطبیق رنگ، واکنشگرا و دسترسیپذیری بالا.
در این پست میخواهم نظراتم را در مورد چگونگی ساخت یک عنصر <button> با رنگ تطبیقپذیر، واکنشگرا و دسترسپذیر به اشتراک بگذارم. نسخه آزمایشی را امتحان کنید و منبع را مشاهده کنید.
اگر ویدیو را ترجیح میدهید، نسخه یوتیوب این پست در اینجا آمده است:
نمای کلی
عنصر <button> برای تعامل با کاربر ساخته شده است. رویداد click آن با استفاده از صفحه کلید، ماوس، لمس، صدا و موارد دیگر فعال میشود و قوانین هوشمندی در مورد زمانبندی آن وجود دارد. همچنین در هر مرورگری چند سبک پیشفرض وجود دارد، بنابراین میتوانید مستقیماً و بدون هیچ گونه سفارشیسازی از آنها استفاده کنید. از color-scheme برای انتخاب دکمههای روشن و تیره ارائه شده توسط مرورگر نیز استفاده کنید.
همچنین انواع مختلفی از دکمهها وجود دارد که هر کدام در کد جاسازی Codepen قبلی نشان داده شدهاند. یک <button> بدون نوع، با قرار گرفتن در یک <form> سازگار میشود و به نوع ارسال تغییر میکند.
<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>
<!-- button state -->
<button disabled></button>
<!-- input buttons -->
<input type="button" />
<input type="file">
در چالش رابط کاربری گرافیکی این ماه، هر دکمه استایلهایی خواهد داشت تا به صورت بصری هدف خود را متمایز کند. دکمههای تنظیم مجدد به دلیل مخرب بودن، رنگهای هشدار دهنده خواهند داشت و دکمههای ارسال متن آبی رنگ خواهند داشت تا کمی تبلیغاتیتر از دکمههای معمولی به نظر برسند.

دکمهها همچنین دارای کلاسهای کاذب برای CSS هستند که برای استایلدهی استفاده میشوند. این کلاسها قلابهای CSS را برای سفارشیسازی حس دکمه ارائه میدهند: :hover برای زمانی که ماوس روی دکمه قرار دارد، :active برای زمانی که ماوس یا صفحهکلید در حال فشار دادن است، و :focus یا :focus-visible برای کمک به استایلدهی فناوری کمکی.
button:hover {}
button:active {}
button:focus {}
button:focus-visible {}

نشانهگذاری
علاوه بر انواع دکمههای ارائه شده توسط مشخصات HTML، یک دکمه با یک آیکون و یک دکمه با کلاس سفارشی btn-custom اضافه کردهام.
<button>Default</button>
<input type="button" value="<input>"/>
<button>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<path d="..." />
</svg>
Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">
سپس، برای آزمایش، هر دکمه درون یک فرم قرار داده میشود. به این ترتیب میتوانم مطمئن شوم که استایلها به طور مناسب برای دکمه پیشفرض، که به عنوان دکمه ارسال عمل میکند، بهروزرسانی میشوند. همچنین استراتژی آیکون را از SVG درونخطی به SVG ماسکشده تغییر میدهم تا مطمئن شوم که هر دو به یک اندازه خوب کار میکنند.
<form>
<button>Default</button>
<input type="button" value="<input>"/>
<button>Icon <span data-icon="cloud"></span></button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom btn-large" type="button">Large Custom</button>
<input type="file">
</form>
ماتریس ترکیبها در این مرحله بسیار گسترده است. بین انواع دکمهها، شبه کلاسها و داخل یا خارج از فرم بودن، بیش از 20 ترکیب دکمه وجود دارد. خوشبختانه CSS میتواند به ما در بیان واضح هر یک از آنها کمک کند!
دسترسیپذیری
عناصر دکمه به طور طبیعی قابل دسترسی هستند، اما چند پیشرفت رایج وجود دارد.
با هم شناور شوید و فوکوس کنید
من دوست دارم :hover و :focus با شبه انتخابگر تابعی :is() گروهبندی کنم. این کار به من کمک میکند تا مطمئن شوم رابطهای من همیشه سبکهای صفحهکلید و فناوریهای کمکی را در نظر میگیرند.
button:is(:hover, :focus) {
…
}
حلقه فوکوس تعاملی
من دوست دارم حلقه فوکوس را برای کاربران کیبورد و فناوریهای کمکی متحرک کنم. من این کار را با متحرک کردن طرح کلی از دکمه به اندازه ۵ پیکسل انجام میدهم، اما فقط زمانی که دکمه فعال نیست. این کار جلوهای ایجاد میکند که باعث میشود حلقه فوکوس هنگام فشار دادن به اندازه دکمه کوچک شود.
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
تضمین کنتراست رنگ عبوری
حداقل چهار ترکیب رنگ مختلف در طیف روشن و تیره وجود دارد که نیاز به بررسی کنتراست رنگ دارند: دکمه، دکمه ارسال، دکمه تنظیم مجدد و دکمه غیرفعال. در اینجا از VisBug برای بررسی و نمایش همزمان همه امتیازات آنها استفاده میشود:
پنهان کردن آیکونها از دید افرادی که نمیتوانند ببینند
هنگام ایجاد یک دکمه آیکون، آیکون باید از متن دکمه پشتیبانی بصری داشته باشد. این همچنین به این معنی است که آیکون برای کسی که دچار کم بینایی است، ارزشمند نیست. خوشبختانه مرورگر راهی برای پنهان کردن موارد از فناوری صفحه خوان ارائه میدهد تا افراد کم بینا با تصاویر دکمه تزئینی اذیت نشوند:
<button>
<svg … aria-hidden="true">...</svg>
Icon Button
</button>

سبکها
در بخش بعدی، ابتدا یک سیستم ویژگی سفارشی برای مدیریت سبکهای تطبیقی دکمه ایجاد میکنم. با استفاده از این ویژگیهای سفارشی میتوانم شروع به انتخاب عناصر و سفارشیسازی ظاهر آنها کنم.
یک استراتژی تطبیقی برای املاک سفارشی
استراتژی ویژگی سفارشی مورد استفاده در این چالش رابط کاربری گرافیکی (GUI Challenge) بسیار شبیه به استراتژی مورد استفاده در ساخت یک طرح رنگی است. برای یک سیستم رنگ روشن و تیره تطبیقی، یک ویژگی سفارشی برای هر تم تعریف و بر اساس آن نامگذاری میشود. سپس یک ویژگی سفارشی واحد برای نگهداری مقدار فعلی تم استفاده میشود و به یک ویژگی CSS اختصاص داده میشود. بعداً، میتوان آن ویژگی سفارشی واحد را به مقدار متفاوتی بهروزرسانی کرد و سپس سبک دکمه را بهروزرسانی کرد.
button {
--_bg-light: white;
--_bg-dark: black;
--_bg: var(--_bg-light);
background-color: var(--_bg);
}
@media (prefers-color-scheme: dark) {
button {
--_bg: var(--_bg-dark);
}
}
چیزی که من دوست دارم این است که تمهای روشن و تیره اعلانی و واضح هستند. غیرمستقیمسازی و انتزاع به ویژگی سفارشی --_bg منتقل شدهاند که اکنون تنها ویژگی "واکنشی" است؛ --_bg-light و --_bg-dark استاتیک هستند. همچنین واضح است که تم روشن، تم پیشفرض است و تم تیره فقط به صورت شرطی اعمال میشود.
آمادهسازی برای ثبات طراحی
انتخابگر مشترک
انتخابگر زیر برای هدف قرار دادن انواع مختلف دکمهها استفاده میشود و در ابتدا کمی گیجکننده است. :where() استفاده میشود، بنابراین سفارشیسازی دکمه نیازی به هیچ ویژگی خاصی ندارد. دکمهها اغلب برای سناریوهای جایگزین تطبیق داده میشوند و انتخابگر :where() تضمین میکند که این کار آسان است. درون :where() ، هر نوع دکمه انتخاب میشود، از جمله ::file-selector-button که نمیتوان آن را درون :is() یا :where() استفاده کرد.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
…
}
تمام ویژگیهای سفارشی درون این انتخابگر قرار میگیرند. وقت آن است که تمام ویژگیهای سفارشی را بررسی کنیم! تعداد زیادی از ویژگیهای سفارشی در این دکمه استفاده شدهاند. من هر گروه را در ادامه شرح خواهم داد، سپس زمینههای تاریک و کاهش حرکت را در انتهای بخش به اشتراک خواهم گذاشت.
رنگ دکمه
دکمهها و آیکونهای ارسال، جای بسیار خوبی برای رنگآمیزی هستند:
--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);
رنگ متن دکمه
رنگ متن دکمهها سفید یا سیاه نیست، بلکه نسخههای تیرهتر یا روشنتر از --_accent با استفاده از hsl() و پایبندی به رنگ hue 210 هستند:
--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);
رنگ پس زمینه دکمه
پسزمینه دکمهها از همان الگوی hsl() پیروی میکنند، به جز دکمههای با تم روشن - این دکمهها روی سفید تنظیم شدهاند تا سطح آنها باعث شود نزدیک به کاربر یا جلوی سایر سطوح به نظر برسند:
--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);
پس زمینه دکمه به خوبی
این رنگ پسزمینه برای نمایش یک سطح در پشت سطوح دیگر است که برای پسزمینه ورودی فایل مفید است:
--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);
پدگذاری دکمه
فاصلهی اطراف متن در دکمه با استفاده از واحد ch انجام میشود که طول نسبی آن به اندازهی فونت بستگی دارد. این موضوع زمانی حیاتی میشود که دکمههای بزرگ بتوانند به سادگی font-size و مقیاس دکمه را به طور متناسب افزایش دهند:
--_padding-inline: 1.75ch;
--_padding-block: .75ch;
حاشیه دکمه
شعاع حاشیه دکمه در یک ویژگی سفارشی ذخیره میشود تا ورودی فایل بتواند با سایر دکمهها مطابقت داشته باشد. رنگهای حاشیه از سیستم رنگ تطبیقی تعیین شده پیروی میکنند:
--_border-radius: .5ch;
--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);
افکت هایلایت دکمه با شناور شدن
این ویژگیها یک ویژگی اندازه برای انتقال در تعامل ایجاد میکنند و رنگ برجسته از سیستم رنگ تطبیقی پیروی میکند. ما نحوه تعامل اینها را بعداً در این پست بررسی خواهیم کرد، اما در نهایت اینها برای جلوه box-shadow استفاده میشوند:
--_highlight-size: 0;
--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);
سایه متن دکمه
هر دکمه یک سایه متن ظریف دارد. این به متن کمک میکند تا روی دکمه قرار گیرد، خوانایی را بهبود میبخشد و یک لایه زیبا از جلوه ظاهری به آن اضافه میکند.
--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);
آیکون دکمه
به لطف واحد طول نسبی ch ، آیکونها به اندازه دو کاراکتر هستند که به تناسب اندازه آیکون با متن دکمه کمک میکند. رنگ آیکون برای رنگی تطبیقی و درون قالبی، به --_accent-color متکی است.
--_icon-size: 2ch;
--_icon-color: var(--_accent);
سایه دکمه
برای اینکه سایهها به درستی با نور و تاریکی سازگار شوند، باید هم رنگ و هم میزان شفافیت خود را تغییر دهند. سایههای با تم روشن زمانی بهترین نتیجه را میدهند که ظریف باشند و به سمت رنگ سطحی که روی آن قرار میگیرند، متمایل باشند. سایههای با تم تیره باید تیرهتر و اشباعتر باشند تا بتوانند رنگهای سطحی تیرهتر را بپوشانند.
--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);
--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);
با رنگها و نقاط قوت تطبیقی میتوانم دو عمق سایه ایجاد کنم:
--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));
--_shadow-2:
0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));
علاوه بر این، برای اینکه دکمهها کمی ظاهری سهبعدی داشته باشند، یک box-shadow 1px این توهم را ایجاد میکند:
--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);
انتقال دکمهها
با پیروی از الگوی رنگهای تطبیقی، دو ویژگی استاتیک برای نگهداری گزینههای سیستم طراحی ایجاد میکنم:
--_transition-motion-reduce: ;
--_transition-motion-ok:
box-shadow 145ms ease,
outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);
همه ویژگیها با هم در انتخابگر
:where( button, input[type="button"], input[type="submit"], input[type="reset"], input[type="file"] ), :where(input[type="file"])::file-selector-button { --_accent-light: hsl(210 100% 40%); --_accent-dark: hsl(210 50% 70%); --_accent: var(--_accent-light);--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);
--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);
--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);
--_padding-inline: 1.75ch; --_padding-block: .75ch;
--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);
--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);
--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);
--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));
--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;
--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);
--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }

سازگاری با تم تاریک
مقدار الگوی props استاتیک -light و -dark زمانی مشخص میشود که props تم تاریک تنظیم شوند:
@media (prefers-color-scheme: dark) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_bg: var(--_bg-dark);
--_text: var(--_text-dark);
--_border: var(--_border-dark);
--_accent: var(--_accent-dark);
--_highlight: var(--_highlight-dark);
--_input-well: var(--_input-well-dark);
--_ink-shadow: var(--_ink-shadow-dark);
--_shadow-depth: var(--_shadow-depth-dark);
--_shadow-color: var(--_shadow-color-dark);
--_shadow-strength: var(--_shadow-strength-dark);
}
}
نه تنها این متن به خوبی خوانده میشود، بلکه مصرفکنندگان این دکمههای سفارشی میتوانند با اطمینان از اینکه این دکمهها به طور مناسب با ترجیحات کاربر سازگار میشوند، از اجزای ساده استفاده کنند.
کاهش سازگاریهای حرکتی
اگر حرکت با این کاربر بازدیدکننده مشکلی ندارد، --_transition به var(--_transition-motion-ok) اختصاص دهید:
@media (prefers-reduced-motion: no-preference) {
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
--_transition: var(--_transition-motion-ok);
}
}
چند سبک مشترک
دکمهها و ورودیها باید فونتهایشان طوری تنظیم شود که از فونتهای بقیه صفحه inherit کنند؛ در غیر این صورت توسط مرورگر استایلدهی میشوند. این موضوع در مورد letter-spacing نیز صدق میکند. تنظیم line-height روی 1.5 اندازه کادر حروف را طوری تنظیم میکند که به متن، فضای خالی در بالا و پایین بدهد:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
/* …CSS variables */
font: inherit;
letter-spacing: inherit;
line-height: 1.5;
border-radius: var(--_border-radius);
}

دکمههای استایلدهی
تنظیم سلکتور
انتخابگر input[type="file"] بخش دکمهی ورودی نیست، بلکه شبه عنصر ::file-selector-button است، بنابراین input[type="file"] از لیست حذف کردهام:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"],
input[type="file"]
),
:where(input[type="file"])::file-selector-button {
}
تنظیمات مکاننما و لمس
ابتدا مکاننما را به سبک pointer استایل میدهم، که به دکمه کمک میکند تا به کاربران ماوس نشان دهد که تعاملی است. سپس touch-action: manipulation اضافه میکنم تا کلیکها نیازی به انتظار نداشته باشند و دابل کلیک احتمالی را مشاهده کنند و باعث شوند دکمهها سریعتر به نظر برسند:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
cursor: pointer;
touch-action: manipulation;
}
رنگها و حاشیهها
در مرحله بعد، اندازه فونت، پسزمینه، متن و رنگ حاشیه را با استفاده از برخی از ویژگیهای سفارشی تطبیقی که قبلاً ایجاد شدهاند، سفارشی میکنم:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
font-size: var(--_size, 1rem);
font-weight: 700;
background: var(--_bg);
color: var(--_text);
border: 2px solid var(--_border);
}

سایهها
دکمهها از تکنیکهای بسیار خوبی استفاده کردهاند. text-shadow با نور و تاریکی تطبیقپذیر است و ظاهری ظریف و دلپذیر از متن دکمه ایجاد میکند که به زیبایی روی پسزمینه قرار میگیرد. برای box-shadow ، سه سایه اختصاص داده شده است. اولین سایه، --_shadow-2 ، یک سایه جعبه معمولی است. سایه دوم برای چشم فریبنده است و باعث میشود دکمه کمی مورب به نظر برسد. سایه آخر برای هایلایت شناور است که در ابتدا با اندازه 0 تنظیم شده است، اما بعداً اندازه آن تغییر میکند و به گونهای تغییر میکند که به نظر برسد از دکمه بزرگتر میشود.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
box-shadow:
var(--_shadow-2),
var(--_shadow-depth),
0 0 0 var(--_highlight-size) var(--_highlight)
;
text-shadow: var(--_ink-shadow);
}

طرح بندی
من به دکمه یک طرحبندی flexbox دادم، به طور خاص یک طرحبندی inline-flex که با محتوای آن متناسب باشد. سپس متن را در مرکز قرار میدهم و عناصر child را به صورت عمودی و افقی در مرکز تراز میکنم. این به آیکونها و سایر عناصر دکمه کمک میکند تا به درستی تراز شوند.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
display: inline-flex;
justify-content: center;
align-items: center;
text-align: center;
}

فاصله گذاری
برای فاصلهگذاری دکمهها، gap برای جلوگیری از تماس خواهر و برادرها و از logical properties برای padding استفاده کردم تا فاصلهگذاری دکمهها برای همه طرحبندیهای متنی کار کند.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
gap: 1ch;
padding-block: var(--_padding-block);
padding-inline: var(--_padding-inline);
}

تجربه کاربری لمسی و ماوس
بخش بعدی بیشتر برای کاربران لمسی در دستگاههای تلفن همراه است. اولین ویژگی، user-select ، برای همه کاربران است؛ این ویژگی از برجسته کردن متن دکمه جلوگیری میکند. این موضوع بیشتر در دستگاههای لمسی قابل توجه است، زمانی که یک دکمه لمس و نگه داشته میشود و سیستم عامل متن دکمه را برجسته میکند.
من معمولاً متوجه شدهام که این تجربه کاربری با دکمهها در برنامههای داخلی مناسب نیست، بنابراین با تنظیم user-select روی هیچکدام، آن را غیرفعال میکنم. رنگهای برجسته کردن ضربه ( -webkit-tap-highlight-color ) و منوهای زمینه سیستم عامل ( -webkit-touch-callout ) از دیگر ویژگیهای دکمههای بسیار وبمحور هستند که با انتظارات عمومی کاربران دکمه همسو نیستند، بنابراین آنها را نیز حذف میکنم.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
user-select: none;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}
انتقالها
متغیر تطبیقی --_transition به ویژگی transition اختصاص داده شده است:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
…
transition: var(--_transition);
}
هنگام نگه داشتن ماوس، در حالی که کاربر به طور فعال دکمه را فشار نمیدهد، اندازه سایه روشن را تنظیم کنید تا ظاهری زیبا به آن بدهید که به نظر برسد از درون دکمه بزرگ میشود:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
):where(:not(:active):hover) {
--_highlight-size: .5rem;
}
پس از فوکوس، فاصلهی خطوط فوکوس از دکمه را افزایش دهید، همچنین به آن ظاهری زیبا بدهید که به نظر میرسد از درون دکمه رشد میکند:
:where(button, input):where(:not(:active)):focus-visible {
outline-offset: 5px;
}
آیکنها
برای مدیریت آیکونها، این انتخابگر یک انتخابگر :where() برای فرزندان یا عناصر SVG مستقیم با ویژگی سفارشی data-icon اضافه کرده است. اندازه آیکون با استفاده از ویژگیهای منطقی درونخطی و بلوکی با ویژگی سفارشی تنظیم میشود. رنگ خط دور و همچنین یک drop-shadow برای مطابقت با text-shadow تنظیم میشود. flex-shrink روی 0 تنظیم شده است تا آیکون هرگز فشرده نشود. در نهایت، من آیکونهای خطدار را انتخاب میکنم و آن سبکها را در اینجا با fill: none و کلاهک خط round و اتصال خطها اختصاص میدهم:
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
) > :where(svg, [data-icon]) {
block-size: var(--_icon-size);
inline-size: var(--_icon-size);
stroke: var(--_icon-color);
filter: drop-shadow(var(--_ink-shadow));
flex-shrink: 0;
fill: none;
stroke-linecap: round;
stroke-linejoin: round;
}

سفارشیسازی دکمههای ارسال
میخواستم دکمههای ارسال کمی ظاهر تبلیغاتی داشته باشند و با تنظیم رنگ متن دکمهها به رنگ تأکیدی، به این هدف رسیدم:
:where(
[type="submit"],
form button:not([type],[disabled])
) {
--_text: var(--_accent);
}

دکمههای تنظیم مجدد را سفارشی کنید
میخواستم دکمههای تنظیم مجدد، علائم هشدار داخلی داشته باشند تا کاربران را از رفتارهای مخرب احتمالیشان آگاه کنند. همچنین تصمیم گرفتم دکمهی تم روشن را با رنگ قرمز بیشتری نسبت به تم تیره طراحی کنم. سفارشیسازی با تغییر رنگ زیرین روشن یا تیرهی مناسب انجام میشود و دکمه، استایل خود را بهروزرسانی میکند:
:where([type="reset"]) {
--_border-light: hsl(0 100% 83%);
--_highlight-light: hsl(0 100% 89% / 20%);
--_text-light: hsl(0 80% 50%);
--_text-dark: hsl(0 100% 89%);
}
همچنین فکر کردم خوب است که رنگ خطوط بیرونی با رنگ قرمز هماهنگ باشد. رنگ متن، قرمز تیره را با قرمز روشن تطبیق میدهد. من رنگ خطوط بیرونی را با کلمه کلیدی currentColor مطابقت میدهم:
:where([type="reset"]):focus-visible {
outline-color: currentColor;
}

دکمههای غیرفعال را سفارشی کنید
خیلی رایج است که دکمههای غیرفعال در حین تلاش برای کوچک کردن دکمه غیرفعال، کنتراست رنگی ضعیفی داشته باشند، بنابراین کمتر فعال به نظر میرسند. من هر مجموعه رنگ را آزمایش کردم و مطمئن شدم که آنها قبول میشوند، و مقدار روشنایی HSL را تا زمانی که امتیاز در DevTools یا VisBug قبول شود، تغییر دادم.
:where(
button,
input[type="button"],
input[type="submit"],
input[type="reset"]
)[disabled] {
--_bg: none;
--_text-light: hsl(210 7% 40%);
--_text-dark: hsl(210 11% 71%);
cursor: not-allowed;
box-shadow: var(--_shadow-1);
}

سفارشیسازی دکمههای ورودی فایل
دکمهی ورودی فایل، یک محفظه برای یک span و یک دکمه است. CSS میتواند محفظهی ورودی و همچنین دکمهی تودرتو را کمی استایلدهی کند، اما نمیتواند span را استایلدهی کند. به محفظه، max-inline-size داده شده است، بنابراین بزرگتر از حد نیازش نمیشود، در حالی که inline-size: 100% به خودش اجازه میدهد تا کوچک شود و محفظههای کوچکتر از اندازهی خودش را در خود جای دهد. رنگ پسزمینه روی یک رنگ تطبیقی تنظیم شده است که تیرهتر از سایر سطوح است، بنابراین به پشت دکمهی انتخاب فایل نگاه میکند.
:where(input[type="file"]) {
inline-size: 100%;
max-inline-size: max-content;
background-color: var(--_input-well);
}
دکمه انتخاب فایل و دکمههای نوع ورودی به طور خاص به appearance: none تا سبکهای ارائه شده توسط مرورگر که توسط سبکهای دکمه دیگر رونویسی نشدهاند، حذف شوند.
:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
appearance: none;
}
در نهایت، حاشیه به inline-end دکمه اضافه میشود تا متن دهانه را از دکمه دور کند و فضایی ایجاد کند.
:where(input[type="file"])::file-selector-button {
margin-inline-end: var(--_padding-inline);
}

استثنائات ویژه تم تاریک
من به دکمههای اکشن اصلی، پسزمینه تیرهتری دادم تا متن با کنتراست بالاتر نمایش داده شود و ظاهری کمی تبلیغاتیتر به آنها بدهم.
@media (prefers-color-scheme: dark) {
:where(
[type="submit"],
[type="reset"],
[disabled],
form button:not([type="button"])
) {
--_bg: var(--_input-well);
}
}

ایجاد انواع
برای سرگرمی و به دلیل کاربردی بودن، تصمیم گرفتم نحوه ایجاد چند نوع مختلف را نشان دهم. یکی از انواع آن بسیار پر جنب و جوش است، شبیه به ظاهر دکمههای اصلی. نوع دیگر بزرگ است. آخرین نوع، آیکونی پر از گرادیان دارد.
دکمه پر جنب و جوش
برای رسیدن به این سبک دکمه، من propهای پایه را مستقیماً با رنگهای آبی بازنویسی کردم. اگرچه این کار سریع و آسان بود، اما propهای تطبیقی را حذف میکند و در هر دو تم روشن و تیره یکسان به نظر میرسد.
.btn-custom {
--_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
--_border: hsl(228 89% 63%);
--_text: hsl(228 89% 100%);
--_ink-shadow: 0 1px 0 hsl(228 57% 50%);
--_highlight: hsl(228 94% 67% / 20%);
}

دکمه بزرگ
این سبک دکمه با تغییر ویژگی سفارشی --_size حاصل میشود. عناصر فاصله و سایر عناصر نسبت به این اندازه هستند و به طور متناسب با اندازه جدید مقیاسبندی میشوند.
.btn-large {
--_size: 1.5rem;
}

دکمه آیکون
این افکت آیکون هیچ ارتباطی با استایلهای دکمه ما ندارد، اما نشان میدهد که چگونه میتوان با چند ویژگی CSS به آن دست یافت، و اینکه دکمه چقدر خوب آیکونهایی را که SVG درونخطی نیستند، مدیریت میکند.
[data-icon="cloud"] {
--icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;
-webkit-mask: var(--icon-cloud);
mask: var(--icon-cloud);
background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}
![]()
نتیجهگیری
حالا که فهمیدی چطور انجامش دادم، تو چطور‽ 🙂
بیایید رویکردهایمان را متنوع کنیم و تمام روشهای ساخت و ساز در وب را یاد بگیریم.
یک نسخه آزمایشی بسازید، لینکها را برایم توییت کنید ، و من آن را به بخش ریمیکسهای انجمن در زیر اضافه خواهم کرد!
ریمیکسهای انجمن
هنوز چیزی برای دیدن اینجا وجود ندارد.
منابع
- کد منبع در گیتهاب