লক্ষ্যবস্তু অবস্থান: স্টিকি উপাদান যা বর্তমানে 'আটকে' অবস্থায় রয়েছে


110

অবস্থান: স্টিকি এখন কিছু মোবাইল ব্রাউজারে কাজ করে, তাই আপনি পৃষ্ঠাটি দিয়ে একটি মেনু বার স্ক্রোল তৈরি করতে পারেন তবে ব্যবহারকারী যখনই এটি স্ক্রোল করে তখন ভিউপোর্টের শীর্ষে স্থির থাকতে পারেন।

তবে আপনি যখন নিজের স্টিকি মেনু বারটি বর্তমানে 'স্টিকিং' করছেন তখন কিছুটা পুনরায় সাজিয়ে নিতে চাইলে কী হবে? উদাহরণস্বরূপ, আপনি যখন বারটি পৃষ্ঠার সাথে স্ক্রোল করছেন তখন বারটি বৃত্তাকার কোণে থাকতে চাইবেন, তবে তারপরেই এটি ভিউপোর্টের শীর্ষে আটকে যাওয়ার সাথে সাথে আপনি শীর্ষ গোলাকার কোণগুলি থেকে মুক্তি পেতে চান এবং নীচে একটি সামান্য ড্রপ ছায়া যুক্ত করতে চান এটা।

সেখানে pseudoselector (যেমন যে কোন ধরণের হয় ::stuckলক্ষ্য উপাদান আছে করার জন্য) position: sticky এবং বর্তমানে অনুগত থাকে? বা পাইপলাইনে ব্রাউজার বিক্রেতাদের কি এরকম কিছু আছে? যদি না হয় তবে আমি কোথায় এটি অনুরোধ করব?

এনবি। জাভাস্ক্রিপ্ট সমাধানগুলি এর জন্য ভাল নয় কারণ scrollব্যবহারকারীরা যখন তাদের আঙুল ছেড়ে দেয় তখন মোবাইলে আপনি কেবলমাত্র একটি ইভেন্ট পান, তাই জেএস ঠিকঠাকটি জানতে পারে না যে স্ক্রোলের প্রান্তটি কেটে গেছে।

উত্তর:


104

বর্তমানে এমন কোনও নির্বাচক নেই যা বর্তমানে 'আটকে' থাকা উপাদানগুলির জন্য প্রস্তাবিত। Postioned লেআউট মডিউল যেখানেposition: sticky সংজ্ঞায়িত করা হয় পারেন এমন কোন নির্বাচক উল্লেখ নেই।

সিএসএসের জন্য বৈশিষ্ট্য অনুরোধগুলি www- শৈলীর মেলিং তালিকায় পোস্ট করা যেতে পারে । আমি বিশ্বাস করি যে একটি :stuckছদ্ম-শ্রেণি ::stuckছদ্ম-উপাদানগুলির চেয়ে আরও বেশি অর্থবোধ করে, যেহেতু আপনি সেই উপাদানগুলিতে থাকা অবস্থায় উপাদানগুলিকে নিজেরাই লক্ষ্য করে দেখছেন। আসলে, কিছুক্ষণ আগে একটি :stuckছদ্ম-শ্রেণি নিয়ে আলোচনা হয়েছিল ; মূল জটিলতা, এটি পাওয়া গেল, এটি হ'ল যে কোনও প্রস্তাবিত নির্বাচক সম্পর্কে জর্জরিত যে একটি রেন্ডারড বা গণিত শৈলীর ভিত্তিতে মিলানোর চেষ্টা করে: বিজ্ঞপ্তি নির্ভরতা।

একটি ক্ষেত্রে :stuckসিউডো-বর্গ, বৃত্ততুল্যতা সহজ ক্ষেত্রে নিম্নলিখিত CSS এর সঙ্গে ঘটবে:

:stuck { position: static; /* Or anything other than sticky/fixed */ }
:not(:stuck) { position: sticky; /* Or fixed */ }

এবং আরও অনেক ধরণের কেস থাকতে পারে যার সমাধান করা কঠিন।

যদিও এটির উপর সাধারণত একমত হয় যে নির্দিষ্ট লেআউট স্টেটের ভিত্তিতে ম্যাচ বাছাইকারী নির্বাচিত হওয়া ভাল হবে , দুর্ভাগ্যক্রমে বড় সীমাবদ্ধতাগুলি বিদ্যমান যা এই অ-তুচ্ছ বাস্তবায়নে পরিণত করে। শীঘ্রই যে কোনও সময় এই সমস্যার খাঁটি সিএসএস সমাধানের জন্য আমি আমার নিঃশ্বাস ত্যাগ করব না।


14
এটা লজ্জার. আমিও এই সমস্যার সমাধান খুঁজছিলাম। positionকোনও :stuckনির্বাচিতের সম্পত্তি উপেক্ষা করা উচিত বলে এমন কোনও নিয়ম চালু করা কি মোটামুটি সহজ হবে না ? (ব্রাউজার বিক্রেতাদের জন্য একটি বিধি, যার অর্থ কীভাবে leftright
ইত্যাদিকে

5
এটি কেবল অবস্থান নয় ... এমন একটি কল্পনা করুন :stuckযা topথেকে মানটি পরিবর্তিত 0হয় 300px, তারপরে নীচে স্ক্রোল করুন 150px... এটি কি আটকে থাকা উচিত? অথবা এমন কোনও উপাদানটির সাথে position: stickyএবং bottom: 0যেখানে :stuckসম্ভবত পরিবর্তিত হতে পারে font-sizeএবং তাই উপাদানগুলির আকারের (তাই এটি যে মুহুর্তে এটি আটকে থাকা উচিত) পরিবর্তন করুন ...
রোমান

3
Github.com/w3c/csswg-drafts/issues/1660 দেখুন যেখানে জেএস ইভেন্টগুলি রাখার প্রস্তাব রয়েছে যাতে কখন কিছু আটকা পড়ে / আনস্টক হয়ে যায়। এটিতে সিউডো-নির্বাচক যে সমস্যাগুলি প্রবর্তন করবেন সেগুলি হওয়া উচিত নয়।
রুবেন

27
আমি বিশ্বাস করি যে ইতিমধ্যে বিদ্যমান সিউডো-ক্লাসগুলি (যেমন: পরিবর্তনশীল প্রস্থের হোভার এবং: নয় (: হোভার) আবার ফিরে যাওয়া) দিয়ে একই বিজ্ঞপ্তিজনিত সমস্যা তৈরি করা যেতে পারে believe আমি পছন্দ করব: সিউডো-ক্লাস আটকেছি এবং মনে করি যে বিকাশকারীকে তার কোডে বিজ্ঞপ্তি সংক্রান্ত সমস্যা না থাকার জন্য দায়বদ্ধ হওয়া উচিত।
মেরেক লিসি

12
ঠিক আছে ... আমি আসলে এটি ভুল হিসাবে বুঝতে পারি না - এটি বলার মতো whileচক্রটি খারাপভাবে তৈরি করা হয়েছে কারণ এটি অফুরন্ত লুপের অনুমতি দেয় :) তবে এটি সাফ করার জন্য ধন্যবাদ;)
মেরেক লিসি

25

কিছু ক্ষেত্রে একটি সহজ IntersectionObserverকৌশলটি করতে পারে, যদি পরিস্থিতি সঠিকভাবে বিচ্ছিন্ন না হয়ে বরং তার মূল ধারকটির বাইরে পিক্সেল বা দু'একটি আটকে থাকতে দেয়। এই পথটি যখন প্রান্তের ঠিক বাইরে গিয়ে বসে, পর্যবেক্ষক গুলি চালায় এবং আমরা ছুটে যাই এবং ছুটে চলেছি।

const observer = new IntersectionObserver( 
  ([e]) => e.target.toggleAttribute('stuck', e.intersectionRatio < 1),
  {threshold: [1]}
);

observer.observe(document.querySelector('nav'));

এর ধারকটির সাথে উপাদানটি ঠিক বাইরে রেখে দিন top: -2pxএবং তারপরে stuckবৈশিষ্ট্যের মাধ্যমে লক্ষ্য করুন ...

nav {
  background: magenta;
  height: 80px;
  position: sticky;
  top: -2px;
}
nav[stuck] {
  box-shadow: 0 0 16px black;
}

উদাহরণ এখানে: https://codepen.io/anon/pen/vqyQEK


1
আমি মনে করি stuckএকটি কাস্টম বৈশিষ্ট্যের চেয়ে কোনও শ্রেণি ভাল হবে ... আপনার পছন্দের কোনও নির্দিষ্ট কারণ আছে কি?
কলিমার্কো

একটি শ্রেণি খুব সূক্ষ্মভাবে কাজ করে, তবে এটি কেবল একটি সামান্য উচ্চ স্তরের বলে মনে হয়, কারণ এটি একটি উদ্ভূত সম্পত্তি। একটি বৈশিষ্ট্য আমার কাছে আরও উপযুক্ত বলে মনে হয় তবে এটি কোনওভাবেই স্বাদের বিষয়।
23:38

ইতিমধ্যে একটি স্থির হেডারের কারণে আমার শীর্ষস্থানটি 60px হওয়া দরকার, তাই আমি আপনার উদাহরণটি কাজ করতে পারি না
FooBar

1
যা কিছু আটকা পড়েছে তাতে কিছু শীর্ষ প্যাডিং যুক্ত করার চেষ্টা করুন, সম্ভবত padding-top: 60pxআপনার ক্ষেত্রে :)
টিম উইলিস

5

Google বিকাশকারী ব্লগে কেউ দাবী একটি সঙ্গে একটি performative জাভাস্ক্রিপ্ট-ভিত্তিক সমাধান পাওয়া আছে IntersectionObserver

এখানে প্রাসঙ্গিক কোড বিট:

/**
 * Sets up an intersection observer to notify when elements with the class
 * `.sticky_sentinel--top` become visible/invisible at the top of the container.
 * @param {!Element} container
 */
function observeHeaders(container) {
  const observer = new IntersectionObserver((records, observer) => {
    for (const record of records) {
      const targetInfo = record.boundingClientRect;
      const stickyTarget = record.target.parentElement.querySelector('.sticky');
      const rootBoundsInfo = record.rootBounds;

      // Started sticking.
      if (targetInfo.bottom < rootBoundsInfo.top) {
        fireEvent(true, stickyTarget);
      }

      // Stopped sticking.
      if (targetInfo.bottom >= rootBoundsInfo.top &&
          targetInfo.bottom < rootBoundsInfo.bottom) {
       fireEvent(false, stickyTarget);
      }
    }
  }, {threshold: [0], root: container});

  // Add the top sentinels to each section and attach an observer.
  const sentinels = addSentinels(container, 'sticky_sentinel--top');
  sentinels.forEach(el => observer.observe(el));
}

আমি নিজেই এটির প্রতিলিপি তৈরি করি নি, তবে সম্ভবত এটি এই প্রশ্নের জন্য কাউকে হোঁচট খেতে সহায়তা করে।


3

স্টাইলিং স্টাফের জন্য জেএস হ্যাকগুলি ব্যবহার করার ভক্ত নয় (যেমন getBoudingClientRect, স্ক্রোল শ্রবণ, পুনরায় আকার শোনার), তবে আমি বর্তমানে সমস্যাটি সমাধান করছি। এই সমাধানটিতে ন্যূনতম / সর্বোচ্চযোগ্য সামগ্রী (<বিবরণ>), বা নেস্টেড স্ক্রোলিং, বা সত্যিই কোনও বাঁকানো বল রয়েছে এমন পৃষ্ঠাগুলির সাথে সমস্যা থাকবে। বলা হচ্ছে, সমস্যাটি যখন সহজ হয় তখন এটির একটি সহজ সমাধান।

let lowestKnownOffset: number = -1;
window.addEventListener("resize", () => lowestKnownOffset = -1);

const $Title = document.getElementById("Title");
let requestedFrame: number;
window.addEventListener("scroll", (event) => {
    if (requestedFrame) { return; }
    requestedFrame = requestAnimationFrame(() => {
        // if it's sticky to top, the offset will bottom out at its natural page offset
        if (lowestKnownOffset === -1) { lowestKnownOffset = $Title.offsetTop; }
        lowestKnownOffset = Math.min(lowestKnownOffset, $Title.offsetTop);
        // this condition assumes that $Title is the only sticky element and it sticks at top: 0px
        // if there are multiple elements, this can be updated to choose whichever one it furthest down on the page as the sticky one
        if (window.scrollY >= lowestKnownOffset) {
            $Title.classList.add("--stuck");
        } else {
            $Title.classList.remove("--stuck");
        }
        requestedFrame = undefined;
    });
})

নোট করুন যে স্ক্রোল ইভেন্ট শ্রোতার মূল থ্রেডে মৃত্যুদন্ড কার্যকর করা হয়েছে যা এটিকে পারফরম্যান্স কিলার করে তোলে। পরিবর্তে ছেদটি পর্যবেক্ষক এপিআই ব্যবহার করুন।
সংশয়ী জুলে

if (requestedFrame) { return; }অ্যানিমেশন ফ্রেম ব্যাচিংয়ের কারণে এটি কোনও "পারফরম্যান্স কিলার" নয়। মোড় নিরীক্ষক এখনও একটি উন্নতি।
সেফ রিড

0

যখন উপাদানটির উপরে আপনার একটি উপাদান থাকে তার জন্য একটি কমপ্যাক্ট উপায় position:sticky। এটি stuckCSS এর সাথে আপনি যে বৈশিষ্ট্যের সাথে মেলে তা নির্ধারণ করে header[stuck]:

এইচটিএমএল:

<img id="logo" ...>
<div>
  <header style="position: sticky">
    ...
  </header>
  ...
</div>

জেএস:

if (typeof IntersectionObserver !== 'function') {
  // sorry, IE https://caniuse.com/#feat=intersectionobserver
  return
}

new IntersectionObserver(
  function (entries, observer) {
    for (var _i = 0; _i < entries.length; _i++) {
      var stickyHeader = entries[_i].target.nextSibling
      stickyHeader.toggleAttribute('stuck', !entries[_i].isIntersecting)
    }
  },
  {}
).observe(document.getElementById('logo'))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.