स्टोरीज़

इस पैटर्न से आपको वेब के लिए स्टोरीज़ कॉम्पोनेंट बनाने का तरीका पता चलता है. यह कॉम्पोनेंट रिस्पॉन्सिव है, कीबोर्ड नेविगेशन के साथ काम करता है, और सभी ब्राउज़र पर काम करता है.

पूरा लेख · YouTube पर वीडियो · GitHub पर सोर्स

<div class="stories"> 
 
<section class="user">
   
<article class="story" style="--bg: url(https://picsum.photos/480/840);"></article>
   
<article class="story" style="--bg: url(https://picsum.photos/480/841);"></article>
 
</section>
 
<section class="user">
   
<article class="story" style="--bg: url(https://picsum.photos/481/840);"></article>
 
</section>
 
<section class="user">
   
<article class="story" style="--bg: url(https://picsum.photos/481/841);"></article>
 
</section>
 
<section class="user">
   
<article class="story" style="--bg: url(https://picsum.photos/482/840);"></article>
   
<article class="story" style="--bg: url(https://picsum.photos/482/843);"></article>
   
<article class="story" style="--bg: url(https://picsum.photos/482/844);"></article>
 
</section>
</div>

       
.stories {
 
display: grid;
 
grid: 1fr / auto-flow 100%;
 
grid-gap: 1ch;
 
gap: 1ch;
 
overflow-x: auto;
 
scroll-snap-type: x mandatory;
 
overscroll-behavior: contain;
 
touch-action: pan-x;
}

.user {
 
scroll-snap-align: start;
 
scroll-snap-stop: always;
 
display: grid;
 
grid: [story] 1fr / [story] 1fr;
}

.story {
 
grid-area: story;

 
background-size: cover;
 
background-image:
    var
(--bg),
    linear-gradient
(to top, rgb(249, 249, 249), rgb(226, 226, 226));

 
user-select: none;
 
touch-action: manipulation;

 
transition: opacity .3s cubic-bezier(0.4, 0.0, 1, 1)
}

.story.seen {
 
opacity: 0;
 
pointer-events: none;
}
       

       
const stories = document.querySelector('.stories')
const median = stories.offsetLeft + (stories.clientWidth / 2)

const state = {
  current_story
: stories.firstElementChild.lastElementChild
}

const navigateStories = direction => {
 
const story = state.current_story
 
const lastItemInUserStory = story.parentNode.firstElementChild
 
const firstItemInUserStory = story.parentNode.lastElementChild
 
const hasNextUserStory = story.parentElement.nextElementSibling
 
const hasPrevUserStory = story.parentElement.previousElementSibling
 
 
if (direction === 'next') {
   
if (lastItemInUserStory === story && !hasNextUserStory)
     
return
   
else if (lastItemInUserStory === story && hasNextUserStory) {
      state
.current_story = story.parentElement.nextElementSibling.lastElementChild
      story
.parentElement.nextElementSibling.scrollIntoView({
        behavior
: 'smooth'
     
})
   
}
   
else {
      story
.classList.add('seen')
      state
.current_story = story.previousElementSibling
   
}
 
}
 
else if(direction === 'prev') {
   
if (firstItemInUserStory === story && !hasPrevUserStory)
     
return
   
else if (firstItemInUserStory === story && hasPrevUserStory) {
      state
.current_story = story.parentElement.previousElementSibling.firstElementChild
      story
.parentElement.previousElementSibling.scrollIntoView({
        behavior
: 'smooth'
     
})
   
}
   
else {
      story
.nextElementSibling.classList.remove('seen')
      state
.current_story = story.nextElementSibling
   
}
 
}
}

stories
.addEventListener('click', e => {
 
if (e.target.nodeName !== 'ARTICLE')
   
return
 
  navigateStories
(
    e
.clientX > median
     
? 'next'
     
: 'prev')
})

// left & right are free with snap points 👍
document
.addEventListener('keydown', ({key}) => {
 
if (key !== 'ArrowDown' || key !== 'ArrowUp')
    navigateStories
(
      key
=== 'ArrowDown'
       
? 'next'
       
: 'prev')
})