التداخل: المحددات والخصائص
التداخل: المحددات والخصائص
التداخل هو واحد من أكثر الميزات المحبوبة في SASS. يسمح لك بكتابة محددات تعكس بنية HTML، مما يجعل كودك أكثر قابلية للقراءة والصيانة. ومع ذلك، مع القوة الكبيرة تأتي مسؤولية كبيرة - التداخل غير الصحيح يمكن أن يؤدي إلى CSS منتفخة ومحددة بشكل مفرط. في هذا الدرس الشامل، سنتقن كلاً من تداخل المحددات وتداخل الخصائص، جنباً إلى جنب مع أفضل الممارسات للحفاظ على كودك نظيفاً.
لماذا التداخل مهم
في CSS العادية، يجب عليك تكرار المحددات الأصلية مراراً وتكراراً:
CSS عادية متكررة
.navigation {
background: #333;
padding: 20px;
}
.navigation ul {
list-style: none;
margin: 0;
}
.navigation ul li {
display: inline-block;
margin-right: 10px;
}
.navigation ul li a {
color: white;
text-decoration: none;
padding: 5px 10px;
}
.navigation ul li a:hover {
background: #555;
}
.navigation ul li a:active {
background: #777;
}
هذا مطول وعرضة للأخطاء وصعب الصيانة. مع تداخل SASS، يمكنك كتابة نفس الأنماط في بنية تعكس HTML الخاص بك:
SCSS نظيفة مع التداخل
.navigation {
background: #333;
padding: 20px;
ul {
list-style: none;
margin: 0;
li {
display: inline-block;
margin-right: 10px;
a {
color: white;
text-decoration: none;
padding: 5px 10px;
&:hover {
background: #555;
}
&:active {
background: #777;
}
}
}
}
}
أنظف بكثير! البنية تمثل بصرياً التسلسل الهرمي لـ HTML، مما يجعلها أسهل في الفهم والتعديل.
كيف تُترجم التداخل إلى CSS
فهم كيفية ترجمة التداخل يساعدك على التنبؤ بالناتج وتجنب الأخطاء. تقوم SASS بتحويل المحددات المتداخلة إلى محددات تابعة في CSS:
إدخال SCSS
.card {
padding: 20px;
.card-header {
font-size: 24px;
}
}
ناتج CSS
.card {
padding: 20px;
}
.card .card-header {
font-size: 24px;
}
يصبح .card-header المتداخل .card .card-header (محدد تابع).
مستويات متعددة من التداخل
SCSS متداخل عميق
.article {
.article-header {
.article-title {
font-size: 32px;
}
}
}
ناتج CSS
.article .article-header .article-title {
font-size: 32px;
}
كل مستوى من التداخل يضيف محدداً آخر إلى السلسلة.
محدد الأصل (&): أفضل صديق لك
الأمبرساند (&) هو حرف خاص يشير إلى المحدد الأصل. إنه ضروري للفئات الزائفة والعناصر الزائفة وفئات المعدل.
الفئات الزائفة مع &
SCSS مع فئات زائفة
.button {
background: #3498db;
color: white;
padding: 10px 20px;
&:hover {
background: #2980b9;
}
&:focus {
outline: 2px solid #3498db;
outline-offset: 2px;
}
&:active {
transform: scale(0.98);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
ناتج CSS
.button {
background: #3498db;
color: white;
padding: 10px 20px;
}
.button:hover {
background: #2980b9;
}
.button:focus {
outline: 2px solid #3498db;
outline-offset: 2px;
}
.button:active {
transform: scale(0.98);
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
العناصر الزائفة مع &
SCSS مع عناصر زائفة
.button {
position: relative;
&::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.1);
opacity: 0;
transition: opacity 0.3s;
}
&:hover::before {
opacity: 1;
}
&::after {
content: "→";
margin-left: 5px;
}
}
:: (نقطتان مزدوجتان) للعناصر الزائفة مثل ::before و ::after، و : (نقطة واحدة) للفئات الزائفة مثل :hover و :focus. هذا هو معيار CSS الحديث.
فئات المعدل مع &
& مثالي لإنشاء فئات المعدل (مثل منهجية BEM):
SCSS مع فئات معدل
.button {
padding: 10px 20px;
background: #3498db;
color: white;
// معدل الفئة: .button.primary
&.primary {
background: #3498db;
}
// معدل الفئة: .button.secondary
&.secondary {
background: #95a5a6;
}
// معدل الفئة: .button.danger
&.danger {
background: #e74c3c;
}
// معدل نمط BEM: .button--large
&--large {
padding: 15px 30px;
font-size: 18px;
}
// معدل نمط BEM: .button--small
&--small {
padding: 5px 10px;
font-size: 12px;
}
}
ناتج CSS
.button {
padding: 10px 20px;
background: #3498db;
color: white;
}
.button.primary {
background: #3498db;
}
.button.secondary {
background: #95a5a6;
}
.button.danger {
background: #e74c3c;
}
.button--large {
padding: 15px 30px;
font-size: 18px;
}
.button--small {
padding: 5px 10px;
font-size: 12px;
}
&.secondary (بدون مسافة) ينشئ .button.secondary (كلتا الفئتين على نفس العنصر)، بينما & .secondary (مع مسافة) سينشئ .button .secondary (محدد تابع).
تنسيق قائم على السياق مع &
يمكنك وضع & في أي مكان في المحدد، حتى بعد محدد آخر:
تنسيق سياق الأصل
.button {
background: blue;
color: white;
// عندما يكون الزر داخل .dark-theme
.dark-theme & {
background: black;
border: 1px solid white;
}
// عندما يكون الزر داخل nav
nav & {
margin-right: 10px;
}
// عندما يكون الزر طفلاً مباشراً لـ .toolbar
.toolbar > & {
margin: 5px;
}
}
ناتج CSS
.button {
background: blue;
color: white;
}
.dark-theme .button {
background: black;
border: 1px solid white;
}
nav .button {
margin-right: 10px;
}
.toolbar > .button {
margin: 5px;
}
تداخل الخصائص
تسمح SASS أيضاً بتداخل الخصائص التي تشترك في نفس البادئة (مثل font- و border- و background-). هذا أقل استخداماً ولكن يمكن أن يقلل من التكرار:
مثال على تداخل الخصائص
.text {
font: {
family: Arial, sans-serif;
size: 16px;
weight: bold;
style: italic;
}
border: {
width: 1px;
style: solid;
color: #ccc;
radius: 4px;
}
background: {
color: white;
image: url('pattern.png');
repeat: no-repeat;
position: center;
}
}
ناتج CSS
.text {
font-family: Arial, sans-serif;
font-size: 16px;
font-weight: bold;
font-style: italic;
border-width: 1px;
border-style: solid;
border-color: #ccc;
border-radius: 4px;
background-color: white;
background-image: url("pattern.png");
background-repeat: no-repeat;
background-position: center;
}
تداخل الخصائص مع الاختصارات
يمكنك الجمع بين تداخل الخصائص وقيم الاختصار:
تداخل خصائص مختلط
.element {
border: 1px solid #ccc {
radius: 4px;
top-color: blue;
}
margin: 0 auto {
top: 20px;
bottom: 20px;
}
}
ناتج CSS
.element {
border: 1px solid #ccc;
border-radius: 4px;
border-top-color: blue;
margin: 0 auto;
margin-top: 20px;
margin-bottom: 20px;
}
أفضل ممارسة: قيّد عمق التداخل (أقصى 3-4 مستويات)
بينما التداخل قوي، التداخل المفرط ينشئ محددات محددة بشكل مفرط يصعب تجاوزها ويمكن أن تضر بالأداء.
تداخل مفرط (سيء)
// لا تفعل هذا
.page {
.container {
.sidebar {
.widget {
.widget-header {
.widget-title {
color: blue; // كابوس الخصوصية!
}
}
}
}
}
}
CSS المترجمة (محددة جداً)
/* هذا المحدد محدد جداً! */
.page .container .sidebar .widget .widget-header .widget-title {
color: blue;
}
.widget-title بشكل مختلف على صفحة معينة، ستحتاج إلى محدد أكثر تحديداً. هذا يؤدي إلى حروب الخصوصية!
نهج أفضل (جيد)
تداخل ضحل مع BEM
// أفضل بكثير!
.widget {
background: white;
padding: 20px;
&__header {
margin-bottom: 15px;
}
&__title {
color: blue;
font-size: 18px;
}
&__content {
line-height: 1.6;
}
&--featured {
border: 2px solid gold;
}
}
CSS المترجمة (خصوصية مثالية)
.widget {
background: white;
padding: 20px;
}
.widget__header {
margin-bottom: 15px;
}
.widget__title {
color: blue;
font-size: 18px;
}
.widget__content {
line-height: 1.6;
}
.widget--featured {
border: 2px solid gold;
}
&__element للعناصر الفرعية و &--modifier للاختلافات. هذا يحافظ على خصوصية منخفضة مع الحفاظ على علاقات واضحة.
خطر التداخل المفرط: انتفاخ الخصوصية
دعنا نرى مثالاً ملموساً على سبب كون التداخل المفرط مشكلة:
مشكلة: SCSS متداخلة بشكل مفرط
.header {
.navigation {
ul {
li {
a {
color: blue;
&:hover {
color: darkblue;
}
}
}
}
}
}
مترجم: محددات عالية التحديد
/* الخصوصية: (0, 0, 5, 0) - عالية جداً! */
.header .navigation ul li a {
color: blue;
}
/* الخصوصية: (0, 1, 5, 0) - أعلى! */
.header .navigation ul li a:hover {
color: darkblue;
}
الآن تخيل أنك تريد تنسيق روابط التنقل بشكل مختلف على صفحة معينة:
محاولة التجاوز (لن تعمل)
/* هذا لن يعمل - ليس محدداً بما فيه الكفاية! */
.special-page .navigation a {
color: red;
}
ستحتاج إلى محدد أكثر تحديداً لتجاوزه، مما يؤدي إلى حرب خصوصية لا نهاية لها.
الحل: تداخل ضحل
نهج أفضل
.navigation {
ul {
list-style: none;
}
&__item {
display: inline-block;
}
&__link {
color: blue;
&:hover {
color: darkblue;
}
}
}
// الآن سهل التجاوز عند الحاجة
.special-page .navigation__link {
color: red;
}
مثال من العالم الحقيقي: مكون بطاقة منسق
دعنا نجمع كل شيء معاً بمثال شامل من العالم الحقيقي:
SCSS لمكون بطاقة كامل
.card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.3s, box-shadow 0.3s;
// حالة التمرير للبطاقة بأكملها
&:hover {
transform: translateY(-4px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}
// صورة البطاقة
&__image {
width: 100%;
height: 200px;
object-fit: cover;
}
// غلاف محتوى البطاقة
&__content {
padding: 20px;
}
// عنوان البطاقة
&__title {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
// رابط متداخل داخل العنوان
a {
color: inherit;
text-decoration: none;
&:hover {
color: #3498db;
}
}
}
// وصف البطاقة
&__description {
color: #666;
line-height: 1.6;
margin-bottom: 15px;
}
// تذييل البطاقة
&__footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 15px;
border-top: 1px solid #eee;
}
// زر البطاقة
&__button {
padding: 8px 16px;
background: #3498db;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background 0.3s;
&:hover {
background: #2980b9;
}
}
// معدل: بطاقة مميزة
&--featured {
border: 2px solid gold;
.card__title {
color: #f39c12;
}
}
// معدل: بطاقة مدمجة
&--compact {
.card__image {
height: 120px;
}
.card__content {
padding: 15px;
}
.card__title {
font-size: 18px;
}
}
// السياق: البطاقة داخل شبكة
.grid & {
margin-bottom: 20px;
}
}
& للمعدلات والحالات، وتنسيق قائم على السياق. ادرس هذا النمط!
التداخل مقابل المحددات المسطحة: متى تستخدم كل منها
استخدم التداخل عندما:
- الأنماط مرتبطة بشكل وثيق بمكون أصل
- تحتاج إلى فئات أو عناصر زائفة (
&:hover) - إنشاء فئات معدل (
&--large) - تنسيق قائم على السياق (
.dark-theme &) - العناصر ذات الصلة تشترك في مساحة اسم (
.card__title)
استخدم المحددات المسطحة عندما:
- يمكن استخدام العناصر بشكل مستقل
- التداخل سيتجاوز 3 مستويات
- تحتاج إلى خصوصية منخفضة لسهولة التجاوز
- إنشاء فئات الأدوات المساعدة (
.text-center)
اعتبارات الأداء
بينما التداخل لا يؤثر بشكل مباشر على حجم ملف CSS (يترجم إلى نفس الناتج)، يمكن للمحددات المحددة بشكل مفرط أن تبطئ عرض المتصفح قليلاً. المتصفحات الحديثة سريعة، لكن المحددات المتداخلة بعمق مثل .a .b .c .d .e .f تستغرق وقتاً أطول للمطابقة من .f.
الخلاصة
التداخل هو ميزة SASS قوية تجعل ملفات الأنماط أكثر قابلية للقراءة والصيانة. لقد تعلمت كيفية تداخل المحددات، واستخدام محدد الأصل (&)، وتداخل الخصائص، والأهم من ذلك، كيفية تجنب الأخطاء الشائعة للتداخل المفرط. حافظ على التداخل ضحلاً (3-4 مستويات كحد أقصى)، تبنَّ منهجية BEM، وستكون SASS الخاصة بك نظيفة وفعالة وقابلة للصيانة!
في الدرس التالي، سنستكشف الأجزاء والاستيرادات - كيفية تنظيم SASS الخاصة بك في ملفات معيارية لبنية مشروع أفضل.
تمرين 1: تحويل CSS المسطح إلى SCSS متداخل
خذ CSS المسطح هذا وحوله إلى SCSS متداخل جيداً:
.product { padding: 20px; }
.product .product-image { width: 100%; }
.product .product-title { font-size: 24px; }
.product .product-title a { color: blue; }
.product .product-title a:hover { color: darkblue; }
.product .product-price { font-weight: bold; color: green; }
.product .product-button { padding: 10px; background: blue; }
.product .product-button:hover { background: darkblue; }
.product.featured { border: 2px solid gold; }
حوّل إلى SCSS متداخل بنمط BEM مع استخدام & الصحيح.
تمرين 2: بناء مكون تنقل
أنشئ شريط تنقل منسق بالكامل باستخدام SCSS متداخل:
- أنشئ
.navمع.nav__listو.nav__itemو.nav__linkمتداخلة - أضف حالات hover و active باستخدام
& - أنشئ معدل
.nav--darkللثيم الداكن - أضف أنماط مستجيبة باستخدام استعلامات الوسائط داخل التداخل
- قم بالترجمة والاختبار مع HTML
تمرين 3: تحديد التداخل المفرط
راجع SCSS المتداخلة بشكل مفرط هذه وأعد بناءها:
.page {
.container {
.content {
.article {
.article-header {
.article-title {
h1 {
color: blue;
}
}
}
}
}
}
}
أعد البناء إلى حد أقصى 2-3 مستويات تداخل مع الحفاظ على علاقات واضحة. استخدم تسمية BEM حيث يكون ذلك مناسباً. وثّق لماذا نسختك المعاد بناؤها أفضل.