قبل أن نبدأ في طرق JavaScript للتعامل مع الأنماط والفئات – إليك قاعدة مهمة. آمل أن يكون الأمر واضحًا بما فيه الكفاية ، ولكن لا يزال يتعين علينا ذكره.
بشكل عام ، هناك طريقتان لتصميم عنصر ما:
- قم بإنشاء فصل دراسي في CSS وإضافته:
<div class="..."> - اكتب الخصائص مباشرة في
style:<div style="...">.
يمكن لـ JavaScript تعديل كل من الفئات و style.
يجب أن نفضل دائمًا فئات CSS على style. يجب استخدام الأخير فقط إذا كانت الفئات “لا يمكنها التعامل معه”.
فمثلا، style يكون مقبولًا إذا قمنا بحساب إحداثيات عنصر ديناميكيًا وأردنا تعيينها من JavaScript ، مثل هذا:
let top = /* حسابات معقدة */;
let left = /* حسابات معقدة */;
elem.style.left = left; // e.g '123px', محسوبة في وقت التشغيل
elem.style.top = top; // e.g '456px'
بالنسبة للحالات الأخرى ، مثل جعل النص أحمر ، إضافة رمز خلفية – صف ذلك في CSS ثم أضف الفئة (يمكن أن تفعل JavaScript ذلك). هذا أكثر مرونة وأسهل للدعم.
className و classList
يعد تغيير الصف أحد الإجراءات الأكثر استخدامًا في البرامج النصية.
في الماضي ، كان هناك قيود في JavaScript: الكلمة المحجوزة مثل "class" لا يمكن أن تكون خاصية كائن. هذا القيد غير موجود الآن ، ولكن في ذلك الوقت كان من المستحيل امتلاك خاصية "class" ، مثل elem.class.
لذلك بالنسبة للفصول ، تم تقديم خاصية "className" ذات المظهر المشابه: يتوافق elem.className مع سمة "class".
على سبيل المثال:
<body class="main page">
<script>
alert(document.body.className); // الصفحة الرئيسية
</script>
</body>
إذا قمنا بتعيين شيء لـ elem.className ، فسيتم استبدال السلسلة الكاملة من الفئات. في بعض الأحيان هذا ما نحتاجه ، ولكن غالبًا ما نريد إضافة / إزالة فصل واحد.
هناك خاصية أخرى لذلك: elem.classList.
إن elem.classList هو كائن خاص مع طرق لإضافة / إزالة / تبديل فئة واحدة.
على سبيل المثال:
<body class="main page">
<script>
// add a class
document.body.classList.add('article');
alert(document.body.className); // مقال الصفحة الرئيسية
</script>
</body>
حتى نتمكن من العمل على كل من سلسلة الفئة الكاملة باستخدام className أو على فئات فردية باستخدام classList. ما نختاره يعتمد على احتياجاتنا.
طرق classList:
elem.classList.add/remove("class")– يضيف / يزيل الصفelem.classList.toggle("class")– يضيف الفصل إذا لم يكن موجودًا ،elem.classList.contains("class")--التحقق من صنف معين ، إرجاعtrue / false.
إلى جانب ذلك ، classList قابلة للتكرار ، لذا يمكننا سرد جميع الفئات for..of ، على النحو التالي:
<body class="main page">
<script>
for (let name of document.body.classList) {
alert(name); //الصفحة الرئيسية ثم الصفحة
}
</script>
</body>
نمط العنصرنمط العنصر
الخاصية elem.style هى كائن يتوافق مع ما هو مكتوب فى سمة النمط "style". يعمل elem.style.width="100px" إعداد بالطريقة نفسها كما لو كان لدينا سمة style سلسلة width:100px.
بالنسبة للملكية المتعددة الكلمات ، يتم استخدام camelCase:
background-color => elem.style.backgroundColor
z-index => elem.style.zIndex
border-left-width => elem.style.borderLeftWidth
على سبيل المثال:
document.body.style.backgroundColor = prompt('background color?', 'green');
خصائص المتصفح المسبوقة مثل
-moz-border-radius, -webkit-border-radius تتبع أيضًا نفس القاعدة: الشرطة تعني الأحرف الكبيرة.
على سبيل المثال:
button.style.MozBorderRadius = '5px';
button.style.WebkitBorderRadius = '5px';
إعادة تعيين خاصية النمط
نرغب أحيانًا في تعيين خاصية نمط وإزالتها لاحقًا.
على سبيل المثال ، لإخفاء عنصر ، يمكننا تعيين elem.style.display = "none".
قد نرغب فى إزالة style.display كما لو لم يتم تعيينه. بدلا من delete elem.style.displayيجب علينا تعيين سلسلة فارغة لها: elem.style.display = "".
// إذا قمنا بتشغيل هذا الرمز ، فسوف يرمش <body>
document.body.style.display = "none"; // إخفاء
setTimeout(() => document.body.style.display = "", 1000); // العودة الى الوضع الطبيعى
إذا وضعنا style.display إلى سلسلة فارغة ، ثم يطبق المتصفح فئات CSS وأنماطه المضمنة بشكل طبيعي ، كما لو لم تكن هناك خاصية style.display على الإطلاق.
style.cssTextعادة نستخدم style.* لتعيين خصائص النمط الفردية. لا يمكننا تعيين النمط الكامل مثل div.style="color: red; width: 100px", لان div.style هو كائن ، وهو للقراءة فقط.
لتعيين النمط الكامل كسلسلة ، هناك خاصية خاصة
style.cssText:
<div id="div">Button</div>
<script>
// يمكننا تعيين علامات نمط خاص مثل "important" هنا
div.style.cssText=`color: red !important;
background-color: yellow;
width: 100px;
text-align: center;
`;
alert(div.style.cssText);
</script>
نادرًا ما يتم استخدام هذه الخاصية ، لأن هذه المهمة تزيل جميع الأنماط الموجودة: فهي لا تضيفها ، ولكنها تحل محلها. قد يحذف أحيانًا شيئًا مطلوبًا. ولكن يمكننا استخدامه بأمان للعناصر الجديدة ، عندما نعلم أننا لن نحذف نمطًا موجودًا.
يمكن تحقيق الشيء نفسه عن طريق تعيين سمة:
div.setAttribute('style', 'color: red...').
احذر الوحدات
لا تنس إضافة وحدات CSS إلى القيم.
على سبيل المثال ، لا ينبغي لنا أن نضع elem.style.top إلى 10، بل بالأحرى 10px. . وإلا فلن يعمل:
<body>
<script>
//لا يعمل!
document.body.style.margin = 20;
alert(document.body.style.margin); // '' (سلسلة فارغة ، يتم تجاهل المهمة)
// أضف الآن وحدة CSS (px) - وهي تعمل
document.body.style.margin = '20px';
alert(document.body.style.margin); // 20px
alert(document.body.style.marginTop); // 20px
alert(document.body.style.marginLeft); // 20px
</script>
</body>
يرجى ملاحظة: المتصفح “يفكك” خاصية style.margin في السطور الأخيرة ويدخل style.marginLeft و style.marginTop منه.
الأنماط المحسوبة: getComputedStyle
لذا ، يعد تعديل النمط أمرًا سهلاً. لكن كيف تقرأه؟
على سبيل المثال ، نريد أن نعرف حجم العنصر وهوامشه ولونه. كيف افعلها؟
تعمل خاصية style فقط على قيمة "style"، بدون أي شلال CSS.
لذلك لا يمكننا قراءة أي شيء يأتي من فئات CSS باستخدام elem.style.
على سبيل المثال ، style هنا لا يرى الهامش:
<head>
<style> body { color: red; margin: 5px } </style>
</head>
<body>
The red text
<script>
alert(document.body.style.color); // فارغة
alert(document.body.style.marginTop); // فارغة
</script>
</body>
… ولكن ماذا لو احتجنا ، على سبيل المثال ، إلى زيادة الهامش بمقدار 20px؟ نريد القيمة الحالية لها.
There’s another method for that: getComputedStyle.
The syntax is:
getComputedStyle(element, [pseudo])
- element
- عنصر لقراءة القيمة لـ.
pseudo
:عنصر زائف إذا لزم الأمر ، على سبيل المثال :: before. سلسلة فارغة أو لا وسيطة تعني العنصر نفسه.
والنتيجة كائن يحتوي على أنماط ، مثل elem.style ، ولكن الآن فيما يتعلق بجميع فئات CSS.
على سبيل المثال:
<head>
<style> body { color: red; margin: 5px } </style>
</head>
<body>
<script>
let computedStyle = getComputedStyle(document.body);
// الآن يمكننا قراءة الهامش واللون منه
alert( computedStyle.marginTop ); // 5px
alert( computedStyle.color ); // rgb(255, 0, 0)
</script>
</body>
هناك مفهومان في CSS:
- قيمة النمط المحسوب هي القيمة بعد تطبيق جميع قواعد CSS ووراثة CSS ، نتيجة سلسلة CSS المتتالية. يمكن أن تبدو
height:1emأوfont-size:125%. - قيمة النمط التي تم
حلهاهي القيمة التي تم تطبيقها أخيرًا على العنصر. مثل القيم1emأو125%نسبي. يأخذ المتصفح القيمة المحسوبة ويجعل جميع الوحدات ثابتة ومطلقة ، على سبيل المثال:height:20pxأوfont-size:16px. . بالنسبة للخصائص الهندسية ، قد تحتوي القيم التي تم حلها على نقطة عائمة ، مثلwidth:50.5px.
منذ وقت طويل تم إنشاء getComputedStyle للحصول على قيم محسوبة ، ولكن اتضح أن القيم التي تم حلها أكثر ملاءمة ، وتغير المعيار.
لذا في الوقت الحاضر ، تُعيد getComputedStyle في الواقع القيمة التي تم حلها للخاصية ، عادةً بالبكسل للهندسة.
getComputedStyle يتطلب اسم الخاصية بالكامليجب أن نسأل دائمًا عن العقار المحدد الذي نريده ، مثل paddingLeft أو marginTop أو borderTopWidth. وإلا فإن النتيجة الصحيحة ليست مضمونة.
على سبيل المثال ، إذا كانت هناك خصائص paddingLeft / paddingTop ، فماذا يجب أن نحصل عليه للحصول على padComputedStyle (elem) .padding؟ لا شيء ، أو ربما قيمة “مولدة” من الحشوات المعروفة؟ لا توجد قاعدة قياسية هنا.
هناك تناقضات أخرى. كمثال ، بعض المتصفحات (Chrome) تظهر 10px في الوثيقة أدناه ، وبعضها
(Firefox) – لا:
<style>
body {
margin: 10px;
}
</style>
<script>
let style = getComputedStyle(document.body);
alert(style.margin); // سلسلة فارغة في Firefox
</script>
:visited الروابط مخفية!قد يتم تلوين الروابط التي تمت زيارتها باستخدام :visited CSS صنف مستعار.
لكن getComputedStyle لا يمنح الوصول إلى هذا اللون ، لأنه بخلاف ذلك يمكن للصفحة العشوائية معرفة ما إذا كان المستخدم قد زار رابطًا عن طريق إنشائه على الصفحة والتحقق من الأنماط.
قد لا ترى JavaScript الأنماط المطبقة بواسطة :visited. وأيضًا ، هناك قيود في CSS تمنع تطبيق أنماط تغيير الهندسة فى :visited. وذلك لضمان عدم وجود طريقة جانبية لصفحة شريرة لاختبار ما إذا كان قد تم زيارة رابط وبالتالي كسر الخصوصية.
ملخص
لإدارة الفئات ، هناك خاصيتين DOM
className– قيمة السلسلة ، جيد لإدارة مجموعة كاملة من الفئات.classList– الكائن بالطرقadd/remove/toggle/contains، جيد للفئات الفردية.
لتغيير الأنماط:
-
خاصية
styleهى كائن له أنماطcamelCased. القراءة والكتابة لها نفس معنى تعديل الخصائص الفردية في سمة"style". لمعرفة كيفية تنفيذimportantوأشياء نادرة أخرى – هناك قائمة بالأساليب على MDN. -
تتوافق الخاصية
style.cssTextمع السمة"style"بأكملها ، وهي السلسلة الكاملة من الأنماط.
لقراءة الأنماط التي تم حلها (فيما يتعلق بجميع الفئات ، بعد تطبيق جميع CSS وحساب القيم النهائية ):
- تُرجع
getComputedStyle (elem، [pseudo])الكائن الشبيه بالنمط معهم. يقرأ فقط.
التعليقات
<code>، وللكثير من السطور استخدم<pre>، ولأكثر من 10 سطور استخدم (plnkr, JSBin, codepen…)