Pseudo-Class و Pseudo-Element در CSS
بهنام نوبخت · ۱۴۰۵/۶/۲۸
تا اینجا با Selectorهای پایه CSS مانند Type، Class، ID و Universal Selector آشنا شدیم و سپس ویژگیهایی مانند float، clear و overflow را یاد گرفتیم. اما در طراحی واقعی صفحات وب، خیلی وقتها لازم است چیزی را انتخاب کنیم که صرفاً با نام تگ، کلاس یا شناسه قابل شناسایی نیست.
برای مثال، ممکن است بخواهیم وقتی کاربر ماوس را روی یک دکمه قرار میدهد، رنگ آن تغییر کند. یا وقتی یک Input فعال میشود، Border متفاوتی داشته باشد. شاید بخواهیم اولین آیتم یک لیست را متفاوت از بقیه نمایش دهیم. حتی ممکن است بخواهیم بدون اضافه کردن یک تگ HTML جدید، یک آیکون، خط تزئینی یا علامت خاصی قبل یا بعد از یک عنصر قرار دهیم.
اینجاست که Pseudo-Class و Pseudo-Element وارد میشوند.
Pseudo-Classها معمولاً برای انتخاب یک عنصر بر اساس وضعیت یا شرایط خاص آن استفاده میشوند، در حالی که Pseudo-Elementها به ما اجازه میدهند بخش خاصی از یک عنصر یا یک بخش مجازی از آن را هدف قرار دهیم.
در این مقاله ابتدا تفاوت این دو مفهوم را یاد میگیریم، سپس مهمترین موارد کاربردی آنها را با مثال بررسی میکنیم.
Pseudo-Class چیست؟
Pseudo-Class یک کلمه کلیدی است که به Selector اضافه میشود تا عنصری را بر اساس وضعیت خاص آن انتخاب کنیم.
Pseudo-Classها معمولاً با یک : شروع میشوند.
ساختار کلی:
selector:pseudo-class {
property: value;
}مثلاً:
button:hover {
background-color: green;
}در این مثال button عنصر اصلی است و :hover مشخص میکند که این قانون فقط زمانی اعمال شود که کاربر روی دکمه قرار گرفته باشد. (developer.mozilla.org)
Pseudo-Class چه تفاوتی با Class دارد؟
این دو مفهوم را نباید با یکدیگر اشتباه بگیریم.
یک Class معمولی را خودمان در HTML تعریف میکنیم:
<button class="primary">ثبت نام</button>سپس:
.primary {
background-color: blue;
}اما Pseudo-Class را در HTML ایجاد نمیکنیم.
مثلاً:
.primary:hover {
background-color: green;
}ما هیچ hoverای در HTML ننوشتهایم.
مرورگر بر اساس وضعیت فعلی عنصر تشخیص میدهد که آیا hover: باید اعمال شود یا خیر.
مهمترین Pseudo-Classهای کاربردی
تعداد Pseudo-Classهای CSS زیاد است و هرکدام کاربرد خاصی دارند. در این دوره فعلاً روی مواردی تمرکز میکنیم که در طراحی روزمره صفحات وب بیشتر با آنها مواجه خواهید شد. (developer.mozilla.org)
مهمترین موارد این مقاله:
:hover
:focus
:active
:visited
:first-child
:last-child
:nth-child()
:first-of-type
:last-of-type
:checked
:disabled
:requiredhover:
یکی از شناختهشدهترین Pseudo-Classها:
:hoverاست.
این Pseudo-Class زمانی فعال میشود که کاربر با Pointer خود روی عنصر قرار بگیرد. (developer.mozilla.org)
مثلاً:
<button class="btn">ثبت نام</button>CSS:
.btn {
background-color: #333;
color: white;
padding: 12px 24px;
border: none;
}
.btn:hover {
background-color: #555;
}در حالت عادی دکمه یک رنگ دارد.
وقتی کاربر ماوس را روی آن قرار دهد، رنگ تغییر میکند.
Hover برای لینک
مثلاً:
a {
color: blue;
}
a:hover {
color: red;
}در این حالت وقتی کاربر روی لینک قرار میگیرد، رنگ آن تغییر میکند.
active:
Pseudo-Class بعدی:
:activeاست.
این حالت زمانی کاربرد دارد که عنصر در حال فعال شدن توسط کاربر باشد؛ برای مثال در لحظه تعامل با یک لینک یا دکمه. (developer.mozilla.org)
مثلاً:
.btn:active {
transform: scale(0.98);
}این تکنیک میتواند باعث شود هنگام کلیک، دکمه کمی فشرده به نظر برسد.
focus:
:focus زمانی استفاده میشود که یک عنصر Focus دریافت کرده باشد.
این موضوع در فرمها اهمیت زیادی دارد.
مثلاً:
<input type="text" placeholder="نام خود را وارد کنید">CSS:
input:focus {
border-color: blue;
outline: none;
}وقتی کاربر روی Input کلیک کند یا با کیبورد به آن برسد، عنصر Focus میشود و این Style اعمال خواهد شد..
چرا Focus مهم است؟
یکی از اشتباهات رایج این است که برای زیبایی طراحی بنویسیم:
input:focus {
outline: none;
}و هیچ جایگزینی برای نشان دادن Focus قرار ندهیم.
این کار میتواند تجربه کاربرانی که با Keyboard کار میکنند را ضعیف کند.
بهتر است اگر Outline را حذف میکنیم، یک نشانه بصری مناسب جایگزین کنیم:
input:focus {
outline: none;
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}به این ترتیب کاربر همچنان میتواند تشخیص دهد که Input فعال است.
focus-visible:
در CSS مدرن با Pseudo-Class دیگری نیز روبهرو میشویم:
:focus-visibleاین Pseudo-Class زمانی کاربرد دارد که مرورگر تشخیص دهد نمایش Focus به صورت بصری برای کاربر مناسب است.
مثلاً:
button:focus-visible {
outline: 3px solid blue;
outline-offset: 3px;
}این تکنیک برای طراحی Accessible بسیار مفید است.
در ادامه دوره هنگام طراحی رابط کاربری و فرمها بیشتر با آن کار خواهیم کرد.
focus-within:
Pseudo-Class کاربردی دیگر:
:focus-withinاست.
این Pseudo-Class به یک عنصر زمانی اعمال میشود که خودش یا یکی از عناصر فرزندش Focus داشته باشد.
مثلاً:
<div class="form-group">
<label>ایمیل</label>
<input type="email">
</div>CSS:
.form-group:focus-within {
border-color: blue;
}وقتی Input داخل .form-group فعال شود، خود .form-group نیز میتواند Style مربوط به :focus-within را دریافت کند.
visited:
برای لینکهایی که کاربر قبلاً بازدید کرده است میتوان از:
:visitedاستفاده کرد.
مثلاً:
a:visited {
color: purple;
}این ویژگی بیشتر برای لینکها کاربرد دارد.
نکته مهم این است که مرورگرها برای حفظ حریم خصوصی کاربر، محدودیتهایی روی Styleهایی که میتوان برای :visited اعمال کرد دارند. بنابراین نباید انتظار داشته باشیم تمام CSS Properties در این حالت آزادانه قابل استفاده باشند.
Pseudo-Classهای مربوط به ساختار HTML
بعضی Pseudo-Classها به موقعیت یک عنصر در بین فرزندانش توجه میکنند.
مهمترین آنها:
:first-child
:last-child
:nth-child()هستند.
first-child:
این Selector اولین فرزند یک والد را انتخاب میکند.
مثلاً:
<ul>
<li>مورد اول</li>
<li>مورد دوم</li>
<li>مورد سوم</li>
</ul>CSS:
li:first-child {
color: red;
}در اینجا اولین li متفاوت نمایش داده میشود.
last-child:
برای انتخاب آخرین فرزند:
li:last-child {
color: blue;
}در مثال قبلی، li سوم انتخاب میشود.
()nth-child:
یکی از قدرتمندترین Pseudo-Classهای ساختاری:
:nth-child()است.
مثلاً:
li:nth-child(2) {
color: red;
}یعنی دومین فرزند را انتخاب کن.
انتخاب آیتمهای زوج
li:nth-child(even) {
background-color: #eee;
}این Selector آیتمهای زوج را انتخاب میکند.
انتخاب آیتمهای فرد
li:nth-child(odd) {
background-color: #ddd;
}این Selector آیتمهای فرد را انتخاب میکند.
این روش برای طراحی جدولها، لیستها و کارتهای پشتسرهم بسیار کاربردی است.
یک مثال کاربردی برای لیست
HTML:
<ul class="menu">
<li>صفحه اصلی</li>
<li>محصولات</li>
<li>خدمات</li>
<li>درباره ما</li>
<li>تماس با ما</li>
</ul>CSS:
.menu li:nth-child(even) {
background-color: #f5f5f5;
}
.menu li:nth-child(odd) {
background-color: white;
}در این حالت پسزمینه آیتمهای زوج و فرد متفاوت میشود.
first-of-type: و last-of-type:
گاهی نمیخواهیم صرفاً اولین فرزند را انتخاب کنیم، بلکه میخواهیم اولین عنصر از یک نوع خاص را انتخاب کنیم.
برای این کار میتوانیم از:
:first-of-typeاستفاده کنیم.
مثلاً:
<div>
<h2>عنوان</h2>
<p>پاراگراف اول</p>
<p>پاراگراف دوم</p>
</div>اگر بنویسیم:
p:first-of-type {
color: red;
}اولین p از نوع p انتخاب میشود.
برای آخرین مورد:
p:last-of-type {
color: blue;
}تفاوت first-child: و first-of-type:
این دو را با هم اشتباه نگیرید.
فرض کنید:
<div>
<h2>عنوان</h2>
<p>پاراگراف اول</p>
<p>پاراگراف دوم</p>
</div>اگر بنویسیم:
p:first-child {
color: red;
}هیچ pای انتخاب نمیشود؛ چون اولین فرزند div یک h2 است.
اما:
p:first-of-type {
color: red;
}اولین p را انتخاب میکند.
Pseudo-Classهای فرم
Pseudo-Classها در فرمها بسیار کاربردی هستند.
مثلاً:
input:required {
border-color: red;
}برای Inputهایی که required هستند.
یا:
input:disabled {
background-color: #eee;
}برای Input غیرفعال.
همچنین:
input:checked {
accent-color: green;
}میتواند برای کنترلهای انتخابشده مانند Checkbox یا Radio کاربرد داشته باشد.
این Pseudo-Classها بر اساس وضعیت فعلی کنترل فرم عمل میکنند.
یک مثال کامل از Pseudo-Classها
HTML:
<div class="card">
<h2>دوره طراحی وب</h2>
<p>
یادگیری HTML و CSS را از پایه شروع کنید.
</p>
<a href="#">مشاهده دوره</a>
</div>CSS:
.card {
width: 300px;
padding: 20px;
border: 1px solid #ddd;
}
.card:hover {
border-color: #2563eb;
}
.card a {
color: #2563eb;
}
.card a:hover {
color: #1d4ed8;
}
.card a:active {
transform: scale(0.98);
}در این مثال بدون اضافه کردن Class جدید، رفتارهای مختلف عنصر را کنترل کردهایم.
Pseudo-Element چیست؟
حالا به مفهوم دوم میرسیم.
Pseudo-Element به ما اجازه میدهد یک بخش خاص یا عنصر مجازی را هدف قرار دهیم؛ بخشی که به صورت یک عنصر HTML معمولی در Markup وجود ندارد.
Pseudo-Elementها معمولاً با دو علامت :: نوشته میشوند.
ساختار:
selector::pseudo-element {
property: value;
}مثلاً:
p::first-letter {
font-size: 40px;
}در اینجا فقط اولین حرف پاراگراف Style میگیرد.
تفاوت اصلی Pseudo-Class و Pseudo-Element
به صورت ساده:
Pseudo-Class
وضعیت یک عنصر را هدف قرار میدهد:
button:hoverیعنی:
دکمه زمانی که Hover شده است.
Pseudo-Element
بخشی از یک عنصر را هدف قرار میدهد:
p::first-letterیعنی:
اولین حرف پاراگراف.
به خاطر سپردن همین تفاوت برای شروع کافی است.
چرا از دو نقطه استفاده میکنیم؟
Pseudo-Class:
:hover
:focus
:first-childPseudo-Element:
::before
::after
::first-letter
::first-lineاستفاده از :: برای Pseudo-Elementها به تفکیک آنها از Pseudo-Classها کمک میکند. مرورگرها برای برخی Pseudo-Elementهای قدیمی مانند ::before و ::after نسخه تکنقطهای را نیز پشتیبانی میکنند، اما در CSS مدرن بهتر است از Syntax دو نقطهای استفاده کنیم.
first-letter::
این Pseudo-Element اولین حرف یک عنصر متنی را هدف قرار میدهد.
مثلاً:
p::first-letter {
font-size: 40px;
font-weight: bold;
}HTML:
<p>
طراحی وب یکی از مهارتهای مهم دنیای فناوری است.
</p>حرف اول پاراگراف بزرگتر و Bold خواهد شد.
first-line::
برای انتخاب اولین خط متن:
p::first-line {
font-weight: bold;
}استفاده میشود.
نکته مهم این است که اولین خط بر اساس اندازه Container و اندازه صفحه تعیین میشود و لزوماً همان بخشی نیست که شما در HTML به عنوان یک خط نوشتهاید.
before::
یکی از پرکاربردترین Pseudo-Elementها:
::beforeاست.
این Pseudo-Element به ما اجازه میدهد محتوای تولیدشده یا یک عنصر تزئینی را قبل از محتوای اصلی قرار دهیم.
مثلاً:
.title::before {
content: "★";
}HTML:
<h2 class="title">دوره طراحی وب</h2>نتیجه چیزی شبیه این خواهد بود:
★ دوره طراحی وبویژگی content
هنگام استفاده از ::before و ::after معمولاً با:
contentروبرو میشویم.
مثلاً:
.title::before {
content: "★";
}بدون content، برای کاربردهای رایج Generated Content معمولاً چیزی نمایش داده نمیشود.
after::
::after مشابه ::before است، با این تفاوت که محتوای تولیدشده را بعد از محتوای عنصر قرار میدهد.
مثلاً:
.title::after {
content: " ✓";
}
اگر HTML این باشد:
<h2 class="title">تکمیل شد</h2>
میتوانیم علامت را بعد از متن نمایش دهیم.
مثال کاربردی before:: و after::
فرض کنید میخواهیم کنار عنوان یک خط تزئینی ایجاد کنیم.
HTML:
<h2 class="section-title">
خدمات ما
</h2>CSS:
.section-title::before {
content: "";
display: inline-block;
width: 40px;
height: 4px;
background-color: orange;
margin-left: 10px;
vertical-align: middle;
}در این مثال چیزی به HTML اضافه نکردهایم، اما CSS یک عنصر مجازی قبل از عنوان ایجاد کرده است.
ساخت Badge با after::
فرض کنید:
<div class="product">
<h3>فروشگاه ساز</h3>
</div>
میخواهیم بدون اضافه کردن یک span جدید، عبارت «جدید» را نمایش دهیم.
CSS:
.product {
position: relative;
}
.product::after {
content: "جدید";
position: absolute;
top: 10px;
right: 10px;
background-color: green;
color: white;
padding: 5px 10px;
border-radius: 5px;
}در اینجا:
.productمرجع Position شده است.::afterیک بخش مجازی ایجاد میکند.contentمتن «جدید» را تولید میکند.position: absoluteآن را در موقعیت مشخص قرار میدهد.
این الگو در طراحی UI بسیار رایج است.
نکته مهم درباره محتوای before:: و after::
نباید هر متن مهم و حیاتی صفحه را فقط با ::before یا ::after ایجاد کنیم.
محتوایی که با Generated Content ساخته میشود ممکن است برای برخی فناوریهای کمکی مانند Screen Readerها به شکل مورد انتظار قابل دسترسی نباشد. به همین دلیل بهتر است اطلاعات مهم و محتوای اصلی را در HTML واقعی قرار دهیم و از Pseudo-Elementها بیشتر برای موارد تزئینی یا نشانههای بصری استفاده کنیم. (developer.mozilla.org)
مثلاً بهتر است:
<button>
حذف حساب
</button>به صورت HTML واقعی وجود داشته باشد، نه اینکه متن مهم Button را فقط با:
button::before {
content: "حذف حساب";
}تولید کنیم.
ترکیب Pseudo-Class و Pseudo-Element
این دو قابلیت را میتوان با هم ترکیب کرد.
مثلاً:
.card:hover::after {
content: "";
display: block;
}در این مثال:
hover:وضعیت عنصر را مشخص میکند.after::عنصر مجازی را مشخص میکند.
مثال جذاب: خط زیر عنوان هنگام Hover
HTML:
<h2 class="title">
خدمات بنو سرویس
</h2>CSS:
.title {
position: relative;
display: inline-block;
}
.title::after {
content: "";
position: absolute;
right: 0;
bottom: -8px;
width: 0;
height: 3px;
background-color: orange;
transition: width 0.3s;
}
.title:hover::after {
width: 100%;
}در این مثال:
after::یک خط مجازی ایجاد میکند.عرض اولیه خط
0است.با
hover:عرض آن100%میشود.transitionباعث حرکت نرم آن میشود.
در اینجا از سه مفهومی که تا اینجا یاد گرفتهایم استفاده کردهایم:
Pseudo-Class
Pseudo-Element
Transition
مثال کاربردی برای لینک
میتوانیم بعد از لینک یک علامت قرار دهیم:
.external-link::after {
content: " ↗";
}HTML:
<a href="#" class="external-link">
مشاهده سایت
</a>این روش برای اضافه کردن نشانههای بصری بسیار کاربردی است.
Pseudo-Elementهای مهم
تا اینجا با چند Pseudo-Element مهم آشنا شدیم:
Pseudo-Element | کاربرد |
|---|---|
| ایجاد بخش مجازی قبل از محتوا |
| ایجاد بخش مجازی بعد از محتوا |
| انتخاب اولین حرف |
| انتخاب اولین خط |
| Style دادن به Placeholder ورودی |
| Style دادن به Marker لیست |
CSS Pseudo-Elementها انواع بسیار بیشتری نیز دارند، اما لازم نیست همه آنها را در این مرحله حفظ کنید.
Style دادن به Placeholder
برای Placeholder فرمها میتوانیم از:
::placeholderاستفاده کنیم.
مثلاً:
input::placeholder {
color: #999;
}HTML:
<input
type="text"
placeholder="نام خود را وارد کنید">در اینجا فقط متن Placeholder Style میگیرد.
Style دادن به Marker لیست
Pseudo-Element دیگری:
::markerاست.
مثلاً:
li::marker {
color: orange;
}این Selector برای Style دادن به Marker آیتمهای لیست کاربرد دارد.
یک پروژه کامل
حالا یک Card ساده طراحی کنیم که از چند مفهوم این مقاله استفاده کند.
HTML
<div class="course-card">
<h2 class="course-title">
آموزش طراحی وب
</h2>
<p>
در این دوره HTML و CSS را از پایه
یاد میگیرید و به صورت مرحلهبهمرحله
وارد طراحی صفحات حرفهای میشوید.
</p>
<a href="#" class="course-link">
مشاهده دوره
</a>
</div>CSS
.course-card {
width: 320px;
padding: 25px;
border: 1px solid #ddd;
border-radius: 12px;
position: relative;
}
.course-card:hover {
border-color: orange;
}
.course-title {
position: relative;
display: inline-block;
}
.course-title::after {
content: "";
position: absolute;
right: 0;
bottom: -8px;
width: 0;
height: 3px;
background-color: orange;
transition: width 0.3s;
}
.course-title:hover::after {
width: 100%;
}
.course-link {
display: inline-block;
margin-top: 15px;
}
.course-link:hover {
color: orange;
}
.course-link:active {
transform: scale(0.98);
}در این پروژه چند مفهوم را با هم ترکیب کردهایم.
hover:
برای تغییر Style هنگام قرار گرفتن Pointer روی عنصر.
active:
برای زمانی که کاربر در حال فعال کردن لینک است.
after::
برای ایجاد خط تزئینی زیر عنوان.
transition
برای ایجاد حرکت نرم هنگام تغییر عرض خط.
تفاوت Pseudo-Class و Pseudo-Element در یک نگاه
ویژگی | Pseudo-Class | Pseudo-Element |
|---|---|---|
Syntax |
|
|
هدف اصلی | وضعیت یا شرایط عنصر | بخش خاص یا عنصر مجازی |
مثال |
|
|
مثال |
|
|
مثال |
|
|
معمولاً نیازمند تعامل؟ | گاهی | معمولاً خیر |
قابل ترکیب؟ | بله | بله |
به شکل خیلی ساده:
button:hoverیعنی:
دکمه وقتی Hover شده است.
اما:
button::afterیعنی:
بخش مجازی بعد از دکمه.
اشتباهات رایج
اشتباه اول: اشتباه گرفتن : و ::
مثلاً:
button::hoverاشتباه است.
باید بنویسیم:
button:hoverو برای Pseudo-Element:
button::afterاشتباه دوم: فراموش کردن content
برای before:: و after:: در کاربردهای Generated Content معمولاً باید:
content: "";یا مقدار دیگری تعیین کنیم.
مثلاً:
.box::before {
content: "";
}اشتباه سوم: استفاده از Pseudo-Element برای محتوای مهم
اطلاعات اصلی صفحه را فقط با CSS تولید نکنید.
بهتر است محتوای مهم در HTML واقعی قرار داشته باشد.
اشتباه چهارم: حذف Focus
این کار:
*:focus {
outline: none;
بدون جایگزین مناسب میتواند تجربه کاربرانی را که با Keyboard کار میکنند خراب کند.
بهتر است Focus را به شکل قابل مشاهده طراحی کنیم.
اشتباه پنجم: استفاده بیش از حد از before:: و after::
Pseudo-Elementها ابزار بسیار خوبی هستند، اما نباید همه چیز را با آنها بسازیم.
اگر یک عنصر واقعاً بخشی از ساختار HTML است، معمولاً بهتر است همان عنصر را در HTML ایجاد کنیم.
تمرینهای مقاله
تمرین ۱
یک Button بسازید که:
در حالت عادی خاکستری باشد.
با
:hoverنارنجی شود.با
:activeکمی کوچک شود.
تمرین ۲
یک Input بسازید که هنگام Focus:
Border آن آبی شود.
Shadow دریافت کند.
Focus آن برای کاربر قابل مشاهده باشد.
تمرین ۳
یک لیست پنجتایی بسازید و:
:nth-child(even)را روی آن اجرا کنید.
سپس:
:nth-child(odd)را امتحان کنید.
تمرین ۴
یک عنوان ایجاد کنید و با استفاده از:
::beforeیک علامت ★ قبل از آن قرار دهید.
تمرین ۵
یک عنوان ایجاد کنید و با after:: یک خط تزئینی زیر آن بسازید.
سپس با:
:hoverکاری کنید که خط از عرض صفر به عرض کامل عنوان برسد.
جمعبندی
در این مقاله با دو مفهوم بسیار مهم CSS یعنی Pseudo-Class و Pseudo-Element آشنا شدیم.
Pseudo-Classها به ما اجازه میدهند عناصر را بر اساس وضعیت یا شرایط خاص آنها انتخاب کنیم. برای مثال:
:hover
:focus
:active
:first-child
:nth-child()از طرف دیگر، Pseudo-Elementها برای هدف قرار دادن بخش خاصی از یک عنصر یا ایجاد بخشهای مجازی استفاده میشوند:
::before
::after
::first-letter
::first-lineیکی از مهمترین نکاتی که باید به خاطر بسپارید این است:
Pseudo-Class → وضعیت عنصر
Pseudo-Element → بخش یا عنصر مجازیاین مفاهیم پایه بسیاری از طراحیهای حرفهای CSS هستند. از ساخت Hover Effect گرفته تا طراحی Badge، خطوط تزئینی، فرمهای تعاملی و بسیاری از Componentهای رابط کاربری، بارها با آنها مواجه خواهید شد.
در مقاله بعدی وارد مرحله دیگری از Selectorها میشویم و یاد میگیریم چگونه بر اساس Attributeها و همچنین ارتباط بین عناصر HTML، Selectorهای دقیقتری بنویسیم.
نظرات
هنوز نظری ثبت نشده است.