دالة scroll-state() في CSS

مثل طلبات البحث في الحاوية، ولكن لطلبات البحث العالقة والمتوقفة والطلبات التي تتضمّن عددًا كبيرًا جدًا من النتائج.

تاريخ النشر: 15 كانون الثاني (يناير) 2025

يستند الإصدار 133 من Chrome إلى طلبات البحث عن الحاوية من خلال تقديم طلبات بحث عن حاويات حالة التمرير. يمكن الآن الاستعلام عن الحالة التي يديرها المتصفّح لموضع العناصر الثابتة ونقاط التمرير السريع والعناصر القابلة للتقديم أو الإيقاف من CSS وتعديلها.

نظرة عامة

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

في ما يلي نظرة عامة على طلبات البحث عن حالة الجهاز المتاحة من الإصدار 133 من Chrome:

حالة "التعليق":
بدء تغييرات في الأنماط عند تثبيت عنصر على أحد الحواف
الحالة المعروضة على الشاشة:
بدء تغييرات النمط عند تثبيت عنصر على محور
حالة التمرير:
بدء تغييرات في الأنماط عند تدفّق عنصر خارج حدوده

والخبر السارّ هو أنّ كل ما تعلمته من طلبات بحث الحاوية سيساعدك في التعامل مع طلبات بحث حالة الانتقال.

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

(على يمين الشاشة) صورة متحركة يتم تشغيلها باستخدام دالة scroll-state()‎، (على يمين الشاشة) صورة متحركة يتم تشغيلها باستخدام التمرير
https://codepen.io/web-dot-dev/pen/emOrBaV

أول طلب بحث عن حالة التمرير

الخطوة الأولى هي تحديد الحاوية باستخدام قيمة جديدة للسمة container-type. كما هو الحال مع طلب البحث عن حاوية، العنصر الذي تريد البحث عنه هو العنصر الذي تمنحه container-type وcontainer-name اختياريًا. باستخدام طلبات البحث عن حالة التمرير، يمكنك منح العنصر الذي يتم تثبيته أو تثبيته أو تجاوزه container-type: scroll-state.

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;
}

الخطوة الثانية هي اختيار العنصر الثانوي للحاوية الذي سيستجيب للحالة، وكما هو الحال مع طلبات البحث عن الحاويات، لا يمكن أن يكون هذا العنصر هو العنصر نفسه الذي يحتوي على container-type.

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    @container scroll-state(stuck: top) {
      background: Highlight;
      color: HighlightText;
    }
  }
}

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

https://codepen.io/web-dot-dev/pen/ByBxpwR

التحسين التدريجي

يمكن أن تسمح لك قاعدة at-rule‏ @supports والدمج بإضافة تحسين تدريجي أو استخدام مشروط للميزات في بضعة أسطر إضافية من الرمز فقط:

.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  @supports (container-type: scroll-state) {
    > nav {
      @container scroll-state(stuck: top) {
        background: Highlight;
        color: HighlightText;
      }
    }
  }
}

احرص أيضًا على استخدام @media (prefers-reduced-motion: no-preference) {} حول الصور المتحركة، إذا كنت بصدد إضافة مؤثرات متحركة إلى العناصر حول الصفحة باستخدام طلبات بحث عن حالة الانتقال.

حالات الاستخدام

عجز عن التقدم

هل يمكن تسمية هذا القسم "المواقف الصعبة"؟ هذه مجموعة صغيرة من حالات استخدام العناصر الثابتة، بالإضافة إلى قسم إضافي من الأفكار التي يجب إنشاؤها.

@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}

قائمة البنية الكاملة

إضافة ظل عند التصاق العنصر

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

https://codepen.io/web-dot-dev/pen/GgKdryj
.stuck-top {
  container-type: scroll-state;
  position: sticky;
  top: 0px;

  > nav {
    transition: box-shadow .3s ease;

    @container scroll-state(stuck: top) {
      box-shadow: var(--shadow-5);
    }
  }
}

تفعيل العنوان الحالي الذي لا يمكن التمرير فوقه

من السيناريوهات الشائعة الأخرى لتلقّي ملاحظات بشأن واجهة المستخدم الملصقة هي تمييز العنصر المُلصق حاليًا. في قائمة بالفرق الموسيقية مرتبة أبجديًا، يمكن أن يكون ذلك مفيدًا للغاية ومفيدًا للتجربة.

https://codepen.io/web-dot-dev/pen/pvzVRaK
.sticky-slide {
  dt {
    container-type: scroll-state;
    position: sticky;
    inset-block-start: 0;
    inset-inline: 0;

    > header {
      transition: 
        background .3s ease,
        box-shadow .5s ease;

      @container scroll-state(stuck: top) {
        background: hsl(265 100% 27%);
        box-shadow: 0 5px 5px #0003;
      }
    }
  }
}

في ما يلي صيغة أخرى، حيث تكون العناوين على جانب عناصر القائمة. هناك الكثير من الخيارات.

https://codepen.io/web-dot-dev/pen/azoGpGg

أفكار إضافية

في ما يلي قائمة بالعروض التوضيحية الثابتة التي قد تمنحك أفكارًا لإضافة لمسة خاصة إلى العرض التجريبي أو إزالة JavaScript، مع طلبات بحث عن حالة الانتقال إلى أعلى أو أسفل الصفحة. نقترح عليك إنشاء أسلوب يعجبك، ما سيساعد في ترسيخ البنية والأفكار 😏.

الصور التي التقطتَها

باستخدام طلبات البحث عن الحالة المُجمَّعة، يمكننا إزالة بعض المسؤوليات من JavaScript وأحداث Snap، ونقل المعالجة إلى CSS.

@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}

قائمة البنية الكاملة

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

a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
    ⤷ a child of the snap target that can query the container for snap state

تحسين العنصر المُلصق بصريًا

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

https://codepen.io/web-dot-dev/pen/NPKMdBX
.demo {
  overflow: auto hidden;
  scroll-snap-type: x mandatory;

  > article {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      > * {
        transition: opacity .5s ease;

        @container not scroll-state(snapped: x) {
          opacity: .25;
        }
      }
    }
  }
}

عرض الترجمة والشرح للعنصر المُدمَج

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

https://codepen.io/web-dot-dev/pen/XJrqpBG
.demo {
  overflow-x: auto;
  scroll-behavior-x: contain;
  scroll-snap-type: x mandatory;

  > .card {
    container-type: scroll-state;
    scroll-snap-align: center;

    @supports (container-type: scroll-state) {
      @media (prefers-reduced-motion: no-preference) {
        figcaption {
          transform: translateY(100%);

          @container scroll-state(snapped: x) {
            transform: translateY(0);
          }
        }
      }
    }
  }
}

إضافة تأثيرات متحركة إلى عناصر الشريحة

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

https://codepen.io/web-dot-dev/pen/dPbeNqY
html {
  scroll-snap-type: y mandatory;
}

section {
  container-type: scroll-state;
  scroll-snap-align: start;
  scroll-snap-stop: always;

  @supports (container-type: scroll-state) {
    @media (prefers-reduced-motion: no-preference) {
      > h1 {
        transition: opacity .5s ease, transform .5s var(--ease-spring-3);
        transition-delay: .5s;
        opacity: 0;
        transform: scale(1.25);

        @container scroll-state(snapped: block) {
          opacity: 1;
          transform: scale(1);
        }
      }
    }
  }
}

قد تلاحظ أنّ جميع طلبات البحث عن حالة CSS المقتطعة تتصرّف مثل scrollsnapchanging، بدلاً من scrollsnapchange. يمنحك ذلك أقرب نقطة ممكنة لتوفير ملاحظات مرئية عن العنصر المُلصق. إذا كان الحدث سريعًا جدًا، ننصحك باستخدام حدث JavaScript.

قابل للتمرير

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

@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}

قائمة البنية الكاملة

الإشارة إلى التمرير باستخدام الظلال

هناك خدعة CSS شهيرة من تأليف Lea Verou تستخدم background-attachment: local لتحقيق تأثير مشابه لهذا، بالإضافة إلى طريقة لتنفيذ ذلك باستخدام الحركة المستندة إلى الانتقال. لكل أسلوب إيجابيات وسلبيات، وعلينا استكشاف الحالات التي يكون فيها كل أسلوب من هذه الأساليب هو الأنسب.

يستخدم المثال التالي عنصرًا واحدًا ثابتًا يمتد على مساحة التمرير. يتضمّن التدرّج اللوني في أعلى الصفحة وتدرّج آخر في أسفلها تأثيرًا متحركًا للعتامة باستخدام @property عند تطبيق طلب البحث عن حالة التمرير السياقي: @container scroll-state(scrollable: top).

يُرجى العلم أيضًا أنّها الحاوية الأولى التي تُعدّ حاوية size وحاوية scroll-state في الوقت نفسه.

https://codepen.io/web-dot-dev/pen/OPLZWBj
.scroll-container {
  container-type: scroll-state size;
  overflow: auto;

  &::after {
    content: " ";

    background: var(--_shadow-top), var(--_shadow-bottom);
    transition: 
      --_scroll-shadow-color-1-opacity .5s ease,
      --_scroll-shadow-color-2-opacity .5s ease;

    @container scroll-state(scrollable: top) {
      --_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
    }

    @container scroll-state(scrollable: bottom) {
      --_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
    }
  }
}
.

طلب السهم

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

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
}

@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
  translate: 0 calc(100% + 10px);
  rotate: .5turn;
}

العودة الى أعلى الصفحة

ومن التفاعلات الشائعة الأخرى في حالة الانتقال إلى أعلى الصفحة هي زرّ "الانتقال إلى أعلى الصفحة". تؤدي التعليمة البرمجية التالية إلى اختفاء زر الانتقال إلى الأعلى عندما لا يكون هناك مكان للانتقال للأعلى.

هذا الحلّ معكوس قليلاً، ولكنه يتيح لك تقليل مقدار CSS. يظهر الزر في مكانه الطبيعي، لذا عليك إخفاؤه عندما لا يكون هناك مكان للانتقال للأعلى.

https://codepen.io/web-dot-dev/pen/OPLZWBj
@container not scroll-state(scrollable: top) {
  translate: 0 calc(100% + 10px);
}

مواصلة الدراسة

إذا كنت بحاجة إلى مزيد من المعلومات، إليك بعض المصادر التي تتراوح بين تفاصيل المواصفات والمقالات الرائعة الأخرى التي تتناول هذا الموضوع: