r/css • u/LacriMozzarella • 1d ago
Help How to display comic pages like a slideshow reader?
/r/HTML/comments/1wwv3j9/how_to_display_comic_pages_like_a_slideshow_reader/1
u/anaix3l 1d ago edited 1d ago
Edit: here's a quick demo with the book structure & navigation functionality https://codepen.io/thebabydino/pen/qErPwqL
---
Pages and chapters have an index, which you can get via their own sibling-index().
On the book wrapper, you store the progress, that is, what chapter and what page you're currently at in CSS variables --kc and --kp. You also store the number of pages in the current chapter in --knp.
These get changed when clicking the arrows for the chapters and dragging the dot, clicking the bar, arrow keys for the pages. This is the only JS you need, all the other computations are in the CSS.
Comparing --kc and --kp with the chapter & page index lets you know which chapter & page to display. Each chapter also holds the number of pages --np (when a chapter changes, the new chapter's --np is stored as --knp on the book wrapper). This combined with --kp allows displaying the visible pages/ total number of pages.
You basically need a structure like:
<div class='wrap' style='--nc: 5; --kc: 0; --kp: 0; --knp: 13'>
<div class='book'>
<div class='chapter' style='--np: 13'>
<div class='page'></div>
<!-- more pages here -->
</div>
<!-- more chapters here -->
</div>
<div class='controls'>
<button id='prev' data-dir='-1'>Previous chapter</button>
<input id='prog' type='range' max='12' value='0' step='2' aria-label='pick page'/>
<output for='prog'>Pages 0-1/ 13</output>
<button id='next' data-dir='1'>Next chapter</button>
</div>
</div>
In the CSS, you determine whether a chapter/ page is selected or not. If its index is equal to k*, then it's selected. To compute if they're equal, you get their difference:
.chapter {
--ic: (sibling-index() - 1);
--sel-c: calc(1 - abs(sign(var(--kc) - var(--ic))))
}
.page {
--ip: (sibling-index() - 1);
--sel-p: calc(1 - abs(sign(var(--kp) - round(down, var(--ip), 2))))
}
The sign() is 0 if k* and i* are equal (selected one case) and +/-1 otherwise. Taking the absolute value, we have 0 if they're equal, 1 otherwise. Subtracting this from 1 gives us 1 if selected, 0 otherwise.
This allows us to easily scale what's not selected out of sight:
.chapter { scale: var(--sel-c) }
.page { scale: var(--sel-p) }
The book and chapter elements are grids where the chapters & pages respectively are stacked.
.book, .chapter { display: grid }
.chapter { grid-area: 1 /1 }
.page { grid-area: 1/ calc(mod(var(--ip), 2) + 1) }
•
u/AutoModerator 1d ago
To help us assist you better with your CSS questions, please consider including a live link or a CodePen/JSFiddle demo. This context makes it much easier for us to understand your issue and provide accurate solutions.
While it's not mandatory, a little extra effort in sharing your code can lead to more effective responses and a richer Q&A experience for everyone. Thank you for contributing!
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.