{"id":"l-css-2-4","courseId":"css-mastery","lang":"ar","kind":"lesson","summary":"حدّد أحجام العناصر من محتواها باستخدام min-content وmax-content وfit-content، واستبدل أزواج الـ breakpoints بـ min() وmax() وclamp().","html":"<p>كان لملخّصات الجلسات في Waypoint الزوج الكلاسيكي من القواعد: <code dir=\"ltr\">width: 100%</code> مع <code dir=\"ltr\">max-width: 40ch</code>، ثم media query لإضافة حشوة جانبية على الهواتف، وأخرى للشاشات الكبيرة. ثلاث قواعد ونقطتا تحوّل لقول شيء واحد: «كن بالعرض المريح للقراءة، لكن لا تتجاوز المساحة المتاحة لك أبدًا».</p>\n<p>تستطيع CSS أن تقول ذلك مباشرةً الآن. يغطّي هذا الدرس أداتين: الكلمات المفتاحية للحجم الذاتي (intrinsic)، التي تترك للمحتوى أن يقرّر حجم العنصر، والدوال الرياضية <code dir=\"ltr\">min()</code> و<code dir=\"ltr\">max()</code> و<code dir=\"ltr\">clamp()</code>، التي تتيح لك وصف مدى بدل اختيار الـ breakpoints.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">دع المحتوى يقرّر: الكلمات المفتاحية الذاتية</h2>\n<p>معظم الأحجام التي تكتبها <em>خارجية</em> (extrinsic): 300px و50% و1fr. لكن المتصفّح يستطيع أيضًا أن يحدّد حجم العنصر من محتواه، وثلاث كلمات مفتاحية تكشف ذلك:</p>\n<ul>\n<li><strong><code dir=\"ltr\">min-content</code></strong>: أضيق ما يمكن أن يكونه العنصر دون أن يفيض، وهو عادةً عرض أطول كلمة فيه.</li>\n<li><strong><code dir=\"ltr\">max-content</code></strong>: العرض الذي سيأخذه المحتوى لو لم يلتفّ أبدًا.</li>\n<li><strong><code dir=\"ltr\">fit-content</code></strong>: هي <code dir=\"ltr\">max-content</code>، لكن لا تتجاوز المساحة المتاحة أبدًا. وحين تنفد المساحة تلتفّ كأيّ كتلة عادية.</li>\n</ul>\n<p><code dir=\"ltr\">fit-content</code> هي التي ستستخدمها أكثر. الشارة أو الزر من نوع block يتمدّد عادةً ليملأ حاويته؛ أما <code dir=\"ltr\">width: fit-content</code> فتجعله يحتضن تسميته كأنه عنصر inline مع بقائه block، فتظل الـ margins والتراصّ تعمل كما يجب. أضف <code dir=\"ltr\">margin-inline: auto</code> فيتوسّط.</p>\n<p>وفي tracks الشبكة تعطيك هذه الكلمات أعمدةً يقودها المحتوى. جدول أعمال Waypoint يستخدم <code dir=\"ltr\">grid-template-columns: max-content 1fr</code>: عمود الوقت بعرض أطول وقت بالضبط («10:15–11:00»)، وعنوان الجلسة يأخذ الباقي.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>استخدام max-content لنصوص المستخدمين</span></p>\n<p><code dir=\"ltr\">max-content</code> لا تلتفّ أبدًا. إنها مثالية للتسميات القصيرة المتحكَّم فيها مثل الأوقات، وكارثة لعنوان جلسة يستطيع أحدهم تعديله، إذ سيمتدّ بسعادة خارج الشاشة. للنصوص التي لا تتحكّم فيها استخدم <code dir=\"ltr\">fit-content</code> أو track بـ <code dir=\"ltr\">minmax()</code>.</p>\n</aside>\n<h2 id=\"sec-2\" tabindex=\"-1\">min() وmax() وclamp()</h2>\n<p>تأخذ الدوال الرياضية قائمة من القيم، بأيّ خليط من الوحدات، وتُحسم إلى طول واحد وقت التخطيط:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"css\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">sizing.css</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.abstract</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  width</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">min</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">%</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">40</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">ch</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);            </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* ceiling: never wider than 40ch */</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.page</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  padding-inline</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">max</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">vw</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);    </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* floor: never less than 1rem */</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.session-card</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  padding</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">clamp</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">12</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">px</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">%</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">32</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">px</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);    </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* between 12px and 32px, 4% in the middle */</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">.content</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  width</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">min</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">100</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">%</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 2</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">60</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">rem</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">);    </span><span style=\"color:#6E7781;--shiki-dark:#8B949E\">/* arithmetic works without calc() */</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">  margin-inline</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">auto</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p><strong><code dir=\"ltr\">min()</code> تُرجع أصغر قيمة</strong>، وهذا يعني أنها تضع حدًّا <em>أعلى</em>. <code dir=\"ltr\">min(100%, 40ch)</code> تساوي 40ch في البطاقة العريضة و100% في الضيّقة؛ فهي تستبدل زوج <code dir=\"ltr\">width</code> و<code dir=\"ltr\">max-width</code> بتصريح واحد. و**<code dir=\"ltr\">max()</code> تُرجع أكبر قيمة**، فتضع حدًّا <em>أدنى</em>: الهامش الجانبي للصفحة 4vw على الشاشات العريضة، لكنه لا يتقلّص أبدًا تحت 1rem على الهاتف.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>قُلها بصوت مرتفع</span></p>\n<p>تبدو الأسماء معكوسة في البداية. اقرأ <code dir=\"ltr\">min(100%, 40ch)</code> على أنها «أيّهما أصغر»، وستكتب الدالة الصحيحة في كل مرة. معظم الناس يحتاجون أسبوعًا من قولها بصوت مرتفع قبل أن تترسّخ.</p>\n</aside>\n<p><strong><code dir=\"ltr\">clamp(MIN, PREFERRED, MAX)</code></strong> تجمع الاثنتين: تُرجع القيمة المفضّلة، لكن لا أقل من MIN ولا أكثر من MAX. وهي بالضبط <code dir=\"ltr\">max(MIN, min(PREFERRED, MAX))</code>.</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 680 220\" role=\"img\" aria-labelledby=\"l-css-2-4-t1\"><defs><marker id=\"arrow-l-css-2-4-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-css-2-4-t1\">رسم بياني للـ padding مقابل عرض الحاوية. الخط مستوٍ عند 12 بكسل للحاويات الضيّقة، ويرتفع مع 4 بالمئة من العرض في المنتصف، ويستوي عند 32 بكسل للحاويات العريضة.</title>\n  <path class=\"d-line\" d=\"M60 180 L640 180\"/>\n  <path class=\"d-line\" d=\"M60 180 L60 20\"/>\n  <text class=\"d-label-muted\" x=\"560\" y=\"204\">عرض الحاوية</text>\n  <text class=\"d-label-muted\" x=\"70\" y=\"30\">padding</text>\n  <path class=\"d-arrow\" d=\"M60 150 L220 150 L440 70 L630 70\"/>\n  <text class=\"d-code\" x=\"90\" y=\"140\">12px (MIN)</text>\n  <text class=\"d-code\" x=\"250\" y=\"100\">4% (PREFERRED)</text>\n  <text class=\"d-code\" x=\"480\" y=\"60\">32px (MAX)</text>\n  <path class=\"d-line d-dashed\" d=\"M220 150 L220 180\"/>\n  <path class=\"d-line d-dashed\" d=\"M440 70 L440 180\"/>\n  <text class=\"d-label-muted\" x=\"196\" y=\"200\">300px</text>\n  <text class=\"d-label-muted\" x=\"416\" y=\"200\">800px</text>\n</svg><figcaption>تتبع clamp() القيمة المفضّلة بين حدّين</figcaption></figure>\n<p>مع <code dir=\"ltr\">clamp(12px, 4%, 32px)</code> تحصل البطاقة في عمود عرضه 300px على 12px من الـ padding، وفي عمود عرضه 500px على 20px، وكل ما هو أعرض من 800px يتوقّف عند 32px. النسب المئوية في الـ padding نسبةً إلى <em>الحجم الأفقي</em> للكتلة الحاوية، لذا تتبع مسافات البطاقة حاويتها لا الـ viewport.</p>\n<h2 id=\"sec-3\" tabindex=\"-1\">وحدات تجعل الدوال الرياضية مفيدة</h2>\n<p>يجب أن تكون القيمة المفضّلة في <code dir=\"ltr\">clamp()</code> شيئًا يتدرّج: نسبة مئوية، أو <code dir=\"ltr\">vw</code>، أو وحدات الحاوية التي ستقابلها في درس <a href=\"/ar/lesson/css-mastery/l-css-2-5\">الـ Container Queries</a>. أما الحدود فيجب أن تكون وحدات مستقرّة مثل <code dir=\"ltr\">px</code> أو <code dir=\"ltr\">rem</code>. واستخدام <code dir=\"ltr\">rem</code> للحدود له ميزة إضافية: إن رفع المستخدم حجم الخط الافتراضي لديه، تتدرّج الحدود معه.</p>\n<p>وهذه أيضًا الحيلة وراء الحماية التي رأيتها في درس grid: <code dir=\"ltr\">minmax(min(180px, 100%), 1fr)</code>. داخل حاوية أضيق من 180px تختار <code dir=\"ltr\">min()</code> القيمة 100%، فلا يفرض الـ track فيضانًا أبدًا.</p>\n<aside class=\"callout callout-note\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/><path d=\"M12 8h.01\"/></svg><span><span class=\"callout-kind\">ملاحظة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>الدعم</span></p>\n<p><code dir=\"ltr\">min()</code> و<code dir=\"ltr\">max()</code> و<code dir=\"ltr\">clamp()</code> والكلمة المفتاحية <code dir=\"ltr\">fit-content</code> لـ <code dir=\"ltr\">width</code> مدعومة في كل المتصفّحات الحالية. ومنذ سنوات يمكن إطلاقها بأمان دون بدائل احتياطية.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">دورك الآن</h2>\n<p>في التمرين بطاقة جلسة داخل غلاف تغيّر الفحوصات عرضه. حدّ الملخّص بـ 40ch دون أن يفيض في البطاقات الضيّقة، واجعل الشارة تحتضن نصّها، وأعطِ البطاقة padding يتدرّج بين 12px و32px. وبعدها ستجعل components كاملة تغيّر تخطيطها بحسب عرض حاويتها، باستخدام الـ container queries.</p>\n","toc":[{"id":"sec-1","text":"دع المحتوى يقرّر: الكلمات المفتاحية الذاتية","level":2},{"id":"sec-2","text":"min() وmax() وclamp()","level":2},{"id":"sec-3","text":"وحدات تجعل الدوال الرياضية مفيدة","level":2},{"id":"sec-4","text":"دورك الآن","level":2}],"takeaways":["<code dir=\"ltr\">min-content</code> أضيق ما يمكن أن يكونه العنصر دون أن يفيض، و<code dir=\"ltr\">max-content</code> عرضه دون أيّ التفاف، و<code dir=\"ltr\">fit-content</code> هي max-content محدودةً بالمساحة المتاحة.","<code dir=\"ltr\">min()</code> تختار أصغر قيمة، فتعمل كسقف: <code dir=\"ltr\">width: min(100%, 40ch)</code> لا تتجاوز 40ch أبدًا ولا تفيض خارج حاويتها أبدًا.","<code dir=\"ltr\">max()</code> تعمل كأرضية، و<code dir=\"ltr\">clamp(MIN, PREFERRED, MAX)</code> تُبقي القيمة المرنة بين حدّين.","الدوال الرياضية تقبل وحدات مختلطة وعمليات حسابية، لذا تعمل <code dir=\"ltr\">min(100% - 2rem, 60rem)</code> دون <code dir=\"ltr\">calc()</code> متداخلة."],"further":[{"title":"clamp() (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/clamp"},{"title":"fit-content (MDN)","url":"https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/fit-content"},{"title":"Sizing units (web.dev Learn CSS)","url":"https://web.dev/learn/css/sizing"}],"quiz":[{"q":"<p>لملخّص جلسة <code dir=\"ltr\">width: min(100%, 40ch)</code>، وعرض بطاقته 900px. ما عرض الملخّص؟</p>","options":[{"text":"900px، لأن 100% هي القيمة الأكبر.","why":"<code dir=\"ltr\">min()</code> تُرجع القيمة الأصغر لا الأكبر. ومن السهل الخلط لأنها تعمل كحدّ أقصى."},{"text":"أيّهما أصغر، أي 40ch (نحو 320px عند 16px).","why":"صحيح. 40ch أصغر من 900px فتفوز. وفي بطاقة عرضها 200px ستكون 100% هي الأصغر وتفوز بدلًا منها."},{"text":"40ch، لكنه يفيض حين تكون البطاقة أضيق.","why":"هذا ما تفعله <code dir=\"ltr\">width: 40ch</code> المجرّدة. أما مع <code dir=\"ltr\">min()</code> فتتولّى 100% الأمر لحظة تصبح البطاقة أضيق من 40ch."},{"text":"يعتمد على عرض الـ viewport.","why":"لا <code dir=\"ltr\">100%</code> ولا <code dir=\"ltr\">ch</code> تعتمد على الـ viewport؛ <code dir=\"ltr\">100%</code> نسبةً إلى الكتلة الحاوية."}],"answer":1},{"q":"<p>ما الذي تعطيه <code dir=\"ltr\">padding: clamp(12px, 4%, 32px)</code> لبطاقة في حاوية عرضها 500px؟</p>","options":[{"text":"12px، لأن الحدّ الأدنى ينطبق أولًا دائمًا.","why":"الحدّ الأدنى لا ينطبق إلا حين تنزل القيمة المفضّلة تحته. و4% من 500px تساوي 20px، وهي فوق 12px."},{"text":"32px، لأن clamp() تفضّل الحدّ الأقصى.","why":"الحدّ الأقصى لا ينطبق إلا حين تتجاوزه القيمة المفضّلة."},{"text":"4px، لأن النسبة المئوية من صندوق الـ padding.","why":"النسب المئوية في الـ padding دائمًا نسبةً إلى الحجم الأفقي (inline size) للكتلة الحاوية، وهو هنا 500px."},{"text":"20px، لأن 4% من 500px تقع بين الحدّين.","why":"صحيح. تُرجع clamp() القيمة المفضّلة حين تقع بين الحدّ الأدنى والحدّ الأقصى."}],"answer":3},{"q":"<p>شارة «Sold out» لها <code dir=\"ltr\">display: block</code> داخل بطاقة، وهي تتمدّد على عرض البطاقة كله. أيّ تصريح يجعلها تحتضن نصّها لكن تلتفّ إن كان النص أطول من البطاقة؟</p>","options":[{"text":"<code dir=\"ltr\">width: max-content</code>","why":"<code dir=\"ltr\">max-content</code> لا تلتفّ أبدًا، فستفيض التسمية الطويلة خارج البطاقة."},{"text":"<code dir=\"ltr\">width: min-content</code>","why":"<code dir=\"ltr\">min-content</code> تلتفّ عند كل فرصة، فتنكسر التسمية ذات الكلمتين على سطرين."},{"text":"<code dir=\"ltr\">width: fit-content</code>","why":"صحيح. تستخدم عرض max-content حين تتوفّر المساحة، وترجع إلى العرض المتاح حين لا تتوفّر."}],"answer":2},{"q":"<p>لماذا تصلح <code dir=\"ltr\">max(1rem, 4vw)</code> هامشًا جانبيًا جيدًا للصفحة؟</p>","options":[{"text":"تكبر مع الـ viewport لكنها لا تنزل أبدًا تحت 1rem على الشاشات الصغيرة.","why":"صحيح. <code dir=\"ltr\">max()</code> تختار القيمة الأكبر، فتعمل كأرضية عند 1rem بينما تتولّى 4vw الأمر على الشاشات الأعرض."},{"text":"لا تكبر أبدًا فوق 1rem، فتُبقي الشاشات العريضة مرتّبة.","why":"هذه <code dir=\"ltr\">min(1rem, 4vw)</code>، وهي تعمل كسقف."},{"text":"تنتقل من rem إلى vw عند breakpoint تعلنه أنت.","why":"لا يوجد breakpoint؛ المتصفّح يقارن القيمتين باستمرار عند كل عرض."}],"answer":0}],"exercise":{"kind":"web","mode":"dom","starter":{"html":"<div class=\"wrap\">\n  <article class=\"session-card\">\n    <span class=\"badge\">Sold out</span>\n    <h3>Intrinsic Sizing in Practice</h3>\n    <p class=\"abstract\">Let content decide how big things are: min-content, max-content, fit-content and the math functions that replace half your media queries.</p>\n  </article>\n</div>","css":".wrap {\n  width: 600px; /* the checks change this width */\n}\n.session-card {\n  border: 1px solid #e5e7eb;\n  border-radius: 12px;\n}\n.session-card h3 { margin: 8px 0; }\n.badge {\n  display: block;\n  padding: 0.1em 0.6em;\n  border-radius: 999px;\n  background: #fee2e2;\n  color: #991b1b;\n}\n\n.session-card { padding: 24px; }\n.abstract { width: 40ch; }\n"},"solution":{"html":"<div class=\"wrap\">\n  <article class=\"session-card\">\n    <span class=\"badge\">Sold out</span>\n    <h3>Intrinsic Sizing in Practice</h3>\n    <p class=\"abstract\">Let content decide how big things are: min-content, max-content, fit-content and the math functions that replace half your media queries.</p>\n  </article>\n</div>","css":".wrap {\n  width: 600px; /* the checks change this width */\n}\n.session-card {\n  border: 1px solid #e5e7eb;\n  border-radius: 12px;\n}\n.session-card h3 { margin: 8px 0; }\n.badge {\n  display: block;\n  padding: 0.1em 0.6em;\n  border-radius: 999px;\n  background: #fee2e2;\n  color: #991b1b;\n}\n\n.session-card { padding: clamp(12px, 4%, 32px); }\n.abstract { width: min(100%, 40ch); }\n.badge { width: fit-content; }\n"},"checks":[{"id":"abstract-capped","test":"const setW = async (w) => { $('.wrap').style.width = w + 'px'; await tick(16); }; await setW(600); const a = $('.abstract'); const probe = document.createElement('div'); probe.style.cssText = 'width:40ch;height:0;font:inherit;'; a.after(probe); const ch40 = probe.getBoundingClientRect().width; probe.remove(); return Math.abs(a.getBoundingClientRect().width - ch40) < 1;"},{"id":"abstract-fits-narrow","test":"const setW = async (w) => { $('.wrap').style.width = w + 'px'; await tick(16); }; const pad = () => parseFloat(style('.session-card', 'padding-left')); await setW(220); const card = $('.session-card').getBoundingClientRect(); const r = $('.abstract').getBoundingClientRect(); const ok = r.right <= card.right - pad() + 0.5; await setW(600); return ok;"},{"id":"badge-hugs","test":"const card = $('.session-card').getBoundingClientRect(); const b = $('.badge').getBoundingClientRect(); return style('.badge', 'display') === 'block' && b.width < card.width / 2 && b.width > 20;"},{"id":"padding-min","test":"const setW = async (w) => { $('.wrap').style.width = w + 'px'; await tick(16); }; const pad = () => parseFloat(style('.session-card', 'padding-left')); await setW(250); const p = pad(); await setW(600); return Math.abs(p - 12) < 0.5;"},{"id":"padding-fluid","test":"const setW = async (w) => { $('.wrap').style.width = w + 'px'; await tick(16); }; const pad = () => parseFloat(style('.session-card', 'padding-left')); await setW(500); const p = pad(); await setW(600); return Math.abs(p - 20) < 0.5;"},{"id":"padding-max","test":"const setW = async (w) => { $('.wrap').style.width = w + 'px'; await tick(16); }; const pad = () => parseFloat(style('.session-card', 'padding-left')); await setW(1000); const p = pad(); await setW(600); return Math.abs(p - 32) < 0.5;"}],"title":"حدّد حجم البطاقة من محتواها","prompt":"<p>تغيّر الفحوصات عرض <code dir=\"ltr\">.wrap</code> بين 220px و1000px. دون media queries:</p>\n<ol>\n<li>اجعل <code dir=\"ltr\">.abstract</code> بعرض <strong>40ch</strong> على الأكثر، لكن لا يتجاوز أبدًا صندوق المحتوى في البطاقة.</li>\n<li>اجعل <code dir=\"ltr\">.badge</code> (وهي من نوع block) تحتضن نصّها بدل أن تتمدّد (أبقِ <code dir=\"ltr\">display: block</code>).</li>\n<li>أعطِ <code dir=\"ltr\">.session-card</code> قيمة padding تساوي <strong>4%</strong> من عرض الغلاف، لا تقل أبدًا عن <strong>12px</strong> ولا تزيد أبدًا على <strong>32px</strong>.</li>\n</ol>\n","hints":["كل مهمة تصريح واحد. فكّر: سقف، احتضان، مدى.","<code dir=\"ltr\">min()</code> تعمل كسقف، وكلمة مفتاحية تجعل الـ block يحتضن محتواه، و<code dir=\"ltr\">clamp()</code> تأخذ ثلاث قيم.","<code dir=\"ltr\">.abstract { width: min(100%, 40ch); }</code> و<code dir=\"ltr\">.badge { width: fit-content; }</code> و<code dir=\"ltr\">.session-card { padding: clamp(12px, 4%, 32px); }</code>."],"explanation":"<p><code dir=\"ltr\">width: min(100%, 40ch)</code> تُحسم إلى أيّهما أصغر، فيتوقّف الملخّص عند 40ch في البطاقة العريضة ويتقلّص إلى صندوق المحتوى في الضيّقة، حيث كانت <code dir=\"ltr\">40ch</code> المجرّدة ستفيض. و<code dir=\"ltr\">fit-content</code> تحدّد عرض الشارة بعرض max-content الخاص بها، محدودًا بالمساحة المتاحة، مع بقائها block. و<code dir=\"ltr\">clamp(12px, 4%, 32px)</code> تُرجع 4% من عرض الكتلة الحاوية (20px عند 500px)، لكنها لا تنزل أبدًا تحت 12px ولا ترتفع فوق 32px، فيستبدل تصريح واحد نقطتي تحوّل.</p>\n","checkLabels":{"abstract-capped":"في البطاقة العريضة عرض الملخّص 40ch","abstract-fits-narrow":"في البطاقة الضيّقة لا يفيض الملخّص","badge-hugs":"الشارة تحتضن نصّها وتبقى block","padding-min":"الـ padding لا ينزل أبدًا تحت 12px","padding-fluid":"الـ padding يساوي 4% من العرض فيما بين الحدّين","padding-max":"الـ padding لا يتجاوز أبدًا 32px"}},"words":593,"readMinutes":3}