تحديد موضع الإرساء

عند وضع تلميح أداة أو قائمة منسدلة، غالبًا ما تريد تحديد موضعها بالنسبة إلى عنصر آخر على الصفحة. على الرغم من توفّر طرق تستخدم تحديد الموضع المطلق لتحقيق هذا التأثير، كانت المتطلبات الأكثر تعقيدًا تلجأ في السابق إلى تحديد موضع العناصر باستخدام JavaScript.

توفّر ميزة "تحديد موضع عنصر الارتساء في CSS" طريقة لتحديد موضع عنصر بشكل تصريحي بالنسبة إلى عنصر آخر.

عناصر الربط

لتحويل عنصر إلى رابط ثابت، عليك منحه قيمة anchor-name لأي سلسلة تبدأ بشرطتين. هذا هو المعرّف الذي سيستخدمه العنصر الموضّع للعثور على عنصر الربط، ومن المفيد منحه اسمًا وصفيًا. يمكنك حتى منح عنصر أسماء مرجعية متعددة، إذا كان سيتم استخدامه كمرجع بطرق مختلفة.

عليك ضبط بعض السمات على العنصر الذي تم تحديد موضعه كي يمكن ربطه. أولاً، عليك إخراج العنصر من تدفّق المستند، ليصبح عائمًا، وذلك من خلال ضبط position: absolute أو position: fixed.

بعد ذلك، عليك تحديد نقطة الربط التي تريد ربط الجهاز بها من خلال ضبط position-anchor على اسم نقطة الربط الذي ضبطته على نقطة الربط.

أخيرًا، عليك تحديد كيفية وضع نقطة الارتكاز. سنتعرّف على المزيد حول position-area لاحقًا في هذه الوحدة.

#anchor {
   anchor-name: --my-anchor;
}

#positionedElement {
     position: absolute;
     position-anchor: --my-anchor;
     position-area: end;
}

الربط الضمني

أما النوافذ المنبثقة، فيمكن ربطها بسهولة أكبر. عند فتح نافذة منبثقة باستخدام زر يتضمّن popovertarget أو من خلال ضبط source باستخدام showPopover({source})، يتمّ ضبط "عنصر ربط ضمني" للنافذة المنبثقة تلقائيًا. بما أنّ النافذة المنبثقة تظهر تلقائيًا مع position: fixed، كل ما عليك فعله لتحديد موضعها هو ضبط الموضع.

#anchor{}

#positionedElement {
  position-area: end;
  margin: unset;
}

تحديد نطاق الإعلانات الثابتة المحتملة

يمكنك تنفيذ تحديد موضع العنصر الثابت كجزء من أحد المكوّنات، حتى تتمكّن من استخدام نمط مثل القائمة المنسدلة في مواضع متعددة. إذا كنت تستخدم anchor-name نفسه عدة مرات، كيف تتأكّد من أنّ كل عنصر في الموضع يجد العنصر الثابت الصحيح؟

تتضمّن حلول JavaScript إضافة معرّفات فريدة إلى كل عنصر ربط، ثم الإشارة إلى هذا المعرّف من العنصر الذي تمّ تحديد موضعه. يصبح هذا الأمر مرهقًا، ولكن توفّر CSS حلاً أبسط باستخدام anchor-scope.

تحدّد السمة anchor-scope أسماء الروابط الثابتة التي ستتم مطابقتها فقط بين عنصر وجميع العناصر التابعة له. يقبل هذا الحقل قائمةً باسم واحد أو أكثر من أسماء الروابط الثابتة أو الكلمة الرئيسية all للحدّ من نطاق جميع أسماء الروابط الثابتة المحدّدة.

يُفضّل إضافة anchor-scope إلى عنصر رئيسي لكلّ من العنصر الموضّع وعنصر الربط الذي لا يحتوي على عناصر ربط أخرى بالاسم نفسه. في كثير من الأحيان، يكون هذا في جذر المكوّن القابل لإعادة الاستخدام.

يوضّح المثال التالي الفرق الذي تحدثه السمة anchor-scope عند تطبيقها على عناصر متكرّرة لها القيمة نفسها anchor-name. في المثال، تشير جميع عناصر <img> وبانرات الصور إلى اسم الرابط --image. عند تطبيق anchor-scope على عناصر <li>، لن يتطابق position-anchor: --image إلا مع عنصر <img> ضِمن عنصر <li> نفسه كالبانر، وإلا سيتطابق مع آخر <img> تم عرضه.

إقناع العملاء بالتبديل

بعد ربط العنصر بعنصر الارتساء، حان الوقت لتحديد موضعه. توفّر ميزة "تحديد موضع عنصر ثابت" طريقتَين لتحديد الموضع، وهما position-area والدالة anchor().

position-area

تتيح لك السمة position-area تحديد موضع عنصر حول نقطة الارتكاز من خلال تحديد كلمة رئيسية واحدة أو كلمتَين رئيسيتَين. ويشمل ذلك العديد من حالات الاستخدام الشائعة، وغالبًا ما يكون مكانًا جيدًا للبدء.

طريقة عمل position-area

تعمل position-area من خلال إنشاء حاوية جديدة للعنصر الذي تم ضبط موضعه في منطقة تم إنشاؤها بواسطة حواف العنصر الثابت والحاوية الأصلية للعنصر الذي تم ضبط موضعه.

على الرغم من توفّر العديد من الكلمات الرئيسية لـ position-area، يمكن تقسيمها إلى بضع فئات لتسهيل فهمها. Anchor-tool.com هي أداة رائعة لاستكشاف البنية.

الكلمات الرئيسية المادية

يمكنك استخدام الكلمات الرئيسية المادية top وleft وbottom وright وcenter. على سبيل المثال، سيؤدي استخدام position-area: top right إلى وضع العنصر الموضّع أعلى نقطة الربط وإلى يسارها. تحتوي هذه الكلمات الرئيسية أيضًا على مكافئات المحور الفعلي، وهي y-start وx-start وy-end وx-end.

الكلمات الرئيسية المنطقية

يمكنك أيضًا استخدام الكلمات الرئيسية المنطقية، block-start وblock-end وinline-start وinline-end. على سبيل المثال، سيؤدي استخدام position-area: block-end inline-start إلى وضع العنصر الموضّع أسفل العنصر الثابت وإلى يساره في لغات مثل الإنجليزية، أو بعد العنصر الثابت على محور الكتلة وقبل العنصر الثابت على المحور المضمّن في وضع الكتابة الخاص بالمستند. يمكن أيضًا استخدام center مع كلمة رئيسية منطقية.

يمكنك أيضًا حذف المحور إذا كنت تحدّد كلمات رئيسية منطقية، مع تحديد محور الكتلة أولاً ثم المحور المضمّن ثانيًا. position-area: start end هو نفسه position-area: block-start inline-end أو حتى position-area: inline-end block-start.

الامتداد على مساحات شبكة متعددة

حتى الآن، ربما لاحظت أنّ هذه الخيارات تسمح لك فقط بوضع العنصر الموضّع ضمن مساحة شبكة واحدة. تؤدي إضافة البادئة span إلى السمات الفعلية أو المنطقية إلى إضافة مساحة شبكة المركز المجاورة. سيتم وضع position-area: span-top right على يمين العنصر الأساسي، ومن أسفل العنصر الأساسي إلى أعلى الحاوية الأصلية للعنصر الذي تم وضعه.

موضع منطقة شائع للقائمة المنسدلة هو position-area: block-end span-inline-end.

تمتد الكلمة الرئيسية span-all على 3 صفوف أو أعمدة.

كلمة رئيسية واحدة

إذا ضبطت كلمة رئيسية واحدة فقط، سيتم ضبط المحور الآخر تلقائيًا. تعمل هذه الميزة إلى حدّ كبير على النحو المتوقّع، ولكن قد يكون من المفيد فهم طريقة عملها.

إذا كانت الكلمة الرئيسية المقدَّمة واضحة بشأن محورها، يتم احتساب المحور الآخر على أنّه span-all. هذا يعني أنّ position-area: bottom يساوي position-area: bottom span-all، وسيكون العنصر الذي تم تحديد موضعه أسفل العنصر الأساسي، وسيتوفّر له العرض الكامل للحاوية.

من ناحية أخرى، إذا لم تشِر الكلمة الرئيسية بوضوح إلى أحد المحاور، يتم تكرارها. position-area: start تعادل start start، ويتم وضعها في أعلى يمين العنصر الثابت في اللغات التي تُكتب من اليسار إلى اليمين.

الدالة anchor()

في حالات الاستخدام المتقدّم، قد لا تستوفي position-area متطلباتك. تتيح لك الدالة anchor() ضبط خصائص فردية للوحة المضمّنة استنادًا إلى موضع عنصر آخر. يؤدي ذلك إلى الحصول على طول CSS، ما يعني أنّه يمكنك استخدامه في العمليات الحسابية ومع دوال CSS الأخرى. بالإضافة إلى ذلك، يمكنك أيضًا ربط جوانب مختلفة بمثبتات مختلفة.

تأخذ الدالة anchor() اسم رابط وموضع رابط. إذا كان العنصر يتضمّن عنصر ربط تلقائيًا، سواء تم ضبطه باستخدام position-anchor أو بشكل ضمني، مثلاً باستخدام عنصر منبثق، يمكنك حذف اسم عنصر الربط.

.positionedElement {
  block-start: anchor(--my-anchor start);
  /*  OR  */
  position-anchor: --my-anchor;
  block-start: anchor(start);
}

القيم الاحتياطية

إذا لم يتم العثور على عنصر أساسي للدالة anchor()، سيكون التعريف بأكمله غير صالح. قد يحدث ذلك إذا تم عرض عنصر الربط بعد العنصر الموضّع، أو إذا لم يكن هناك عنصر يحمل anchor-name مطابقًا. للتعامل مع هذه الحالة، يمكنك ضبط مدة أو نسبة احتياطية.

.positionedElement {
   block-start: anchor(--my-anchor, 100px)
}

في المثال السابق، يتم ربط القيمة اليسرى للعنصر الموضّع بالعنصر --focused-anchor، ولكن لا يتوفّر العنصر anchor-name إلا عند تمرير مؤشر الماوس فوق الزر الأول أو التركيز عليه. بما أنّ الدالة anchor() تؤدي إلى تحديد طول، يمكنك استخدام مرجع آخر كبديل. إذا لم نقدّم عنصرًا احتياطيًا، لن يتم تحديد موضع العنصر المحدد.

الكلمات الرئيسية على الجانب

تحدّد قيمة جانب العنصر الثابت الحافة التي سيتم وضع العنصر الثابت مقابلها. على غرار position-area، تتوافق قيمة جهة عنصر التثبيت مع عدة أنواع مختلفة من التركيبات.

النوع القيم الوصف
طبيعية top، وleft، وbottom، وright

تتطابق الكلمات الرئيسية الفعلية مع جانب معيّن من العنصر الثابت، ولكن لا يمكن استخدامها إلا على المحور نفسه الذي يتم فيه ضبط موضع العنصر المحدّد.

على سبيل المثال، يضع top: anchor(bottom) الجزء العلوي من العنصر في الجزء السفلي من العنصر الأساسي، ولكن لن يعمل left: anchor(top).

جانب الصفحة inside، outside

تتوافق الكلمة الرئيسية inside مع الجانب نفسه لسمة inset، وتتوافق الكلمة الرئيسية outside مع الجانب المقابل على المحور نفسه.

على سبيل المثال، يشير inset-block-start: anchor(inside) إلى الجانب block-start من علامة الارتساء، ويشير inset-inline-end: (outside) إلى الجانب inline-start من علامة الارتساء.

منطقي start، وend، وself-start، وself-end

تشير الكلمات الرئيسية المنطقية إلى جوانب عنصر الرابط استنادًا إلى وضع الكتابة للعنصر الذي تمّ تحديد موضعه باستخدام self-start وself-end، أو إلى وضع الكتابة للكتلة الحاوية للعنصر الذي تمّ تحديد موضعه باستخدام start وend.

النسبة المئوية ‫0% - 100%

تضع قيمة النسبة المئوية العنصر الموضّع على طول المحور من بداية العنصر الأساسي إلى نهايته على المحور المحدّد. يقع 0% على الجانب start من نقطة الارتكاز، بينما يقع 100% على الجانب الآخر من نقطة الارتكاز. center تعادل 50%. إذا كنت تستخدم نسبة مئوية في موضع إدراج على الجانب الأخير مثل bottom، لن يتم عكس ذلك، وسيظل 0% هو الجانب start لعنصر التثبيت.

يوضّح المثال التالي كيف تنتقل قيمة النسبة المئوية دائمًا من البداية إلى النهاية على المحور المحدّد:

جارٍ استخدام anchor()

بما أنّ anchor() يمثّل طولاً، فهو مرن للغاية. يمكنك تعديل القيمة باستخدام دوال CSS، مثل max() وcalc().

أحد القيود هو أنّه يمكنك استخدام وظائف anchor() على خصائص الإضافات فقط.

يضيف المثال السابق خلفية إلى لوحة التفاصيل المفتوحة يتم تحريكها بسلاسة عند فتح لوحة مختلفة، ويتم توسيعها لتشمل لوحة تفاصيل تم التمرير فوقها. ولتحقيق ذلك، يتم استخدام min() لاختيار الطول الأصغر بين نقطتَي ربط.

#indicator{
/*  Use the smaller of the 2 values:  */
  inset-block-start: min(
/*   1. The start side of the default anchor, which is the open `<details>` element  */
    anchor(start),
/*   2. The start side of the hovered `<details>` element.    */
    anchor(--hovered start,
/*     If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used.   */
       var(calc(1px * infinity)))
  );
}

يستخدم المثال أيضًا calc() لإضافة مساحة مضمّنة حول اللوحة المفتوحة.

استخدام حجم عنصر الربط

يمكنك أيضًا استخدام الدالة anchor-size() لاستخدام أبعاد العنصر الثابت لتحديد حجم العنصر الموضّع أو موضعه أو هامشه.

تأخذ anchor-size() اسم رابط أو تستخدم الرابط التلقائي. بشكلٍ تلقائي، سيتم استخدام حجم العنصر الثابت على المحور الذي يتم استخدامه فيه، وبالتالي ستعرض الدالة width: anchor-size() عرض العنصر الثابت. يمكنك أيضًا استخدام المحور الآخر من خلال تحديد الطول الذي تريده، وذلك باستخدام الكلمات الرئيسية المادية width وheight أو الكلمات الرئيسية المنطقية block وinline وself-block وself-inline.

التعامل مع تجاوز السعة

لقد أنشأت مكوّن قائمة منسدلة، واستخدمت تحديد موضع العنصر الثابت لوضع القائمة المنسدلة في المكان الذي تريده، ولكن بعد ذلك نقلت القائمة إلى الجانب الآخر من الشاشة، أو استخدمتها لقائمة مستخدم، وكان اسم المستخدم طويلاً جدًا. فجأةً، يختفي القائمة المنسدلة من الشاشة. فماذا أفعل الآن؟

يتضمّن تحديد موضع العناصر الثابتة في CSS نظامًا مدمجًا يتيح لك إنشاء مجموعة قوية من البدائل بسرعة عندما ينتهي موضع العنصر خارج الحاوية التي يتضمّنها.

خيارات بديلة

تأخذ قاعدة position-try-fallbacks قائمة بخيارات احتياطية. عندما يفيض الموضع التلقائي، سيتم تجربة كل خيار بالترتيب إلى أن يتم العثور على موضع لا يفيض.

يمكنك استخدام أي قيمة position-area كخيار احتياطي. في هذا المثال، في أوضاع الكتابة من اليمين إلى اليسار، مثل اللغة العربية، سيحاول العنصر الموضّع أن يكون في أسفل العنصر الثابت، ويمتد على العمودَين الأوسط والأيسر. إذا كان المحتوى يفيض، سيحاول الظهور في أسفل عنصر الربط، ويمتد على العمودَين الأيمن والأوسط. وإذا حدث تجاوز في هذا الموضع أيضًا، سيعود الموضع إلى الموضع التلقائي، حتى لو حدث تجاوز فيه.

.positioned-element {
  position-area: block-end span-inline-end;
  position-try-fallbacks: block-end span-inline-start;
}

هناك أيضًا العديد من الكلمات الرئيسية flip- التي تعالج حالات الرجوع الشائعة. تجرب flip-block وflip-inline قلب العنصر على المحورين الأفقي والعمودي. يمكن أيضًا دمجها مع flip-block flip-inline لقلب المحورَين. تعكس قيمة flip-start العنصر الذي تم ضبط موضعه على خط قطري من زوايا بداية العنصر الأساسي إلى زوايا نهايته.

يمكنك أيضًا إنشاء خيار احتياطي مخصّص باستخدام @position-try، ما يتيح لك ضبط الهوامش والمحاذاة وحتى تغيير نقطة الارتكاز.

@position-try --menu-below {
  position-area: bottom span-right;
  margin-top: 1em;
}

#positioned-element {
  position-try: --menu-below;
}

يمكن إضافة flip-block وflip-inline إلى خيارات @position-try الاحتياطية لإنشاء منتج مختلف.

#positioned-element {
  position-try: --menu-below, flip-inline --menu-below;
}

في المثال السابق، يتّبع المتصفّح الخطوات التالية، ويتوقف بمجرد العثور على حلّ لا يؤدي إلى تجاوز السعة.

  1. يتم وضع العنصر مع position-area: end في أسفل يسار العنصر الثابت.
  2. إذا حدث تجاوز، يتم وضع العنصر باستخدام خيار الاحتياط المخصّص المسمّى --bottom-span-right، والذي يضعه مع position-area: bottom span-right، مع هامش إضافي أدناه.
  3. إذا حدث تجاوز للسعة، يتم وضع العنصر باستخدام flip-inline --bottom-span-right، ما يجمع بين خيار العنصر الاحتياطي المخصّص وflip-inline، وهو في الأساس position-area: bottom span-left.
  4. إذا حدث تجاوز للسعة، يتم وضع العنصر باستخدام --use-alternate خيار الاحتياطي المخصّص، ما يؤدي إلى وضعه أسفل عنصر ربط مختلف تمامًا.
  5. إذا حدث تجاوز للسعة، يعود العنصر إلى موضعه الأصلي مع position-area: end، على الرغم من أنّه من المعروف أنّ ذلك سيؤدي إلى تجاوز السعة.

الترتيب الاحتياطي

بشكلٍ تلقائي، عندما يفيض الموضع الأولي، سيحاول المتصفّح استخدام كل خيار في position-try-fallbacks إلى أن يتم العثور على موضع لا يفيض. يمكنك إلغاء هذا السلوك باستخدام position-try-order لاختبار كل خيار احتياطي، واستخدام الخيار الذي يتضمّن أكبر مساحة على محور محدّد.

يمكنك تحديد المحور باستخدام الكلمات الرئيسية المنطقية most-block-size وmost-inline-size أو باستخدام الكلمات الرئيسية الفعلية most-height وmost-width.

يمكن دمج position-try-order وposition-try-fallbacks مع الاختصار position-try، مع وضع الترتيب أولاً.

الانتقال

عندما يتنقّل المستخدم في الصفحة، يتوقّع أن تتحرّك الصفحة بسلاسة. ولتحقيق ذلك، تفرض المتصفّحات قيودًا على كيفية استخدام ميزة "تحديد موضع العنصر الثابت" عند التمرير.

على الرغم من أنّه يمكنك ربط عنصر ثابت بمواضع في حاويات تمرير مختلفة، لن يتحرّك العنصر إلا استجابةً لتمرير أحد المواضع. سيكون هذا هو عنصر الربط التلقائي، وهو إما عنصر الربط الضمني من النافذة المنبثقة أو قيمة position-anchor.

ستلاحظ أنّ العنصر الموضّع يظل مرئيًا حتى عندما يتم تمرير العنصر الأساسي بعيدًا عن منطقة العرض. لإخفاء العنصر الذي تم ضبط موضعه عندما يكون عنصر الربط مخفيًا، اضبط القيمة position-visibility: anchors-visible. لا ينطبق ذلك فقط عندما يتم التمرير السريع فوق العنصر الثابت، ولكن أيضًا إذا كان مخفيًا بطرق أخرى، مثل visibility: hidden.

التحقّق من فهمك

ما هي القيم الصالحة للجانب في anchor()؟

inside
إجابة صحيحة.
25%
إجابة صحيحة.
25px
إجابة غير صحيحة على الرغم من أنّه يمكن استخدام طول مثل 25px كقيمة احتياطية، لا يمكن استخدام سوى النسب المئوية للجانب.
block-start
غير صحيح
start
إجابة صحيحة.

ما هي القيم الصالحة لـ position-area؟

top
إجابة صحيحة.
block-end inline-end
إجابة صحيحة.
block-start block-end
إجابة غير صحيحة يمكنك تحديد عمود أو صف واحد فقط على كل محور.

ما هي المواقع التي تتوافق مع الدالة anchor()؟

top
إجابة صحيحة.
margin-left
إجابة غير صحيحة
inset-block-start
إجابة صحيحة.
transform
إجابة غير صحيحة

ماذا يحدث إذا كانت هناك روابط متعددة تتضمّن anchor-name نفسه؟

يتم تكرار العنصر الذي تمّ تحديد موضعه وربطه بكل تطابق.
إجابة غير صحيحة
يتم ربط العنصر الذي تم تحديد موضعه بالعنصر الأول في المستند.
إجابة غير صحيحة
يكون العنصر الذي تم تحديد موضعه مرتبطًا بالعنصر الأخير في المستند.
إجابة صحيحة.
يتم ربط العنصر الذي تم ضبط موضعه بأقرب عنصر ربط.
إجابة غير صحيحة