Codepen
I have a div that represents a book page and contains the front and the back elements. On a click the page flips to show the reverse side.
In order to make the styling work, I made the book div (which contains the page divs) have position: relative
, and the paper (which represents a page) div has position: absolute
styling.
However, the width and height of the book
are set in px so when the paper content doesn't fit the dimensions, the content overflows:
On pages where the content fits, it looks alright:
How do I make the paper
elements to adjust to the size of the content? So that if there are several pages, the height of each page would be equal to the height of the page with the most amount of content?
let pages = document.getElementsByClassName("paper");
setup(pages);
function setup(elements) {
for (let i = 0; i < elements.length; i++) {
let previous = i === 0 ? null : elements[i - 1];
let element = elements[i];
let next = i === elements.length - 1 ? null : elements[i + 1];
element.addEventListener('click', () => {
element.classList.toggle('flipped');
if (element.classList.contains("flipped")) {
if (next !== null) {
next.style.zIndex++;
}
element.style.zIndex = i + 1;
} else {
element.style.zIndex = elements.length - i;
}
});
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
background-color: #333333;
}
/* Book */
.book {
position: relative;
width: 350px;
height: 500px;
transition: transform 3.5s;
}
.paper {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
perspective: 1500px;
cursor: pointer;
}
.front,
.back {
background-color: white;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
transform-origin: left;
transition: transform 3.5s;
display: flex;
display: flex;
justify-content: center;
align-items: flex-start;
}
.front {
z-index: 1;
backface-visibility: hidden;
border-left: 3px solid powderblue;
background-color: #b3ffff;
}
.back {
z-index: 0;
background-color: #ffd699;
}
.front-content,
.back-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-start;
}
.back-content {
transform: rotateY(180deg)
}
/* Paper flip effect */
.flipped .front,
.flipped .back {
transform: rotateY(-180deg);
}
/* Controller Buttons */
button {
border: none;
background-color: transparent;
cursor: pointer;
margin: 10px;
transition: transform 0.5s;
}
button:focus {
outline: none;
}
button:hover i {
color: #636363;
}
i {
font-size: 50px;
color: gray;
}
/* Paper stack order */
#p1 {
z-index: 3;
}
#p2 {
z-index: 2;
}
#p3 {
z-index: 1;
}
<div id="book" class="book">
<div id="p1" class="paper">
<div class="front">
<div id="f1" class="front-content">
<h1>The Roman Empire was the post-Republican state of ancient Rome. It included territory around the Mediterranean in Europe, North Africa, and Western Asia, and was ruled by emperors. The adoption of Christianity as the state church in 380 and the
fall of the Western Roman Empire conventionally marks the end of classical antiquity and the beginning of the Middle Ages.</h1>
</div>
</div>
<div class="back">
<div id="b1" class="back-content">
<h1>The first two centuries of the Empire saw a period of unprecedented stability and prosperity known as the Pax Romana (lit. 'Roman Peace'). </h1>
</div>
</div>
</div>
<!-- Second page -->
<div id="p2" class="paper">
<div class="front">
<div id="f2" class="front-content">
<h1>Due to the Empire's extent and endurance, its institutions and culture had a lasting influence on the development of language, religion, art, architecture, literature, philosophy, law, and forms of government in its territories. Latin evolved
into the Romance languages, while Medieval Greek became the language of the East.</h1>
</div>
</div>
<div class="back">
<div id="b2" class="back-content">
<h1>he rediscovery of classical science and technology (which formed the basis for Islamic science) in medieval Europe led to the Scientific Renaissance and Scientific Revolution. Many modern legal systems, such as the Napoleonic Code, descend from
Roman law, while Rome's republican institutions have influenced the Italian city-state republics of the medieval period, the early United States, and modern democratic republics.
</h1>
</div>
</div>
</div>
</div>
Codepen
I have a div that represents a book page and contains the front and the back elements. On a click the page flips to show the reverse side.
In order to make the styling work, I made the book div (which contains the page divs) have position: relative
, and the paper (which represents a page) div has position: absolute
styling.
However, the width and height of the book
are set in px so when the paper content doesn't fit the dimensions, the content overflows:
On pages where the content fits, it looks alright:
How do I make the paper
elements to adjust to the size of the content? So that if there are several pages, the height of each page would be equal to the height of the page with the most amount of content?
let pages = document.getElementsByClassName("paper");
setup(pages);
function setup(elements) {
for (let i = 0; i < elements.length; i++) {
let previous = i === 0 ? null : elements[i - 1];
let element = elements[i];
let next = i === elements.length - 1 ? null : elements[i + 1];
element.addEventListener('click', () => {
element.classList.toggle('flipped');
if (element.classList.contains("flipped")) {
if (next !== null) {
next.style.zIndex++;
}
element.style.zIndex = i + 1;
} else {
element.style.zIndex = elements.length - i;
}
});
}
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
width: 100vw;
display: flex;
justify-content: center;
align-items: center;
font-family: sans-serif;
background-color: #333333;
}
/* Book */
.book {
position: relative;
width: 350px;
height: 500px;
transition: transform 3.5s;
}
.paper {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
perspective: 1500px;
cursor: pointer;
}
.front,
.back {
background-color: white;
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
transform-origin: left;
transition: transform 3.5s;
display: flex;
display: flex;
justify-content: center;
align-items: flex-start;
}
.front {
z-index: 1;
backface-visibility: hidden;
border-left: 3px solid powderblue;
background-color: #b3ffff;
}
.back {
z-index: 0;
background-color: #ffd699;
}
.front-content,
.back-content {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-start;
}
.back-content {
transform: rotateY(180deg)
}
/* Paper flip effect */
.flipped .front,
.flipped .back {
transform: rotateY(-180deg);
}
/* Controller Buttons */
button {
border: none;
background-color: transparent;
cursor: pointer;
margin: 10px;
transition: transform 0.5s;
}
button:focus {
outline: none;
}
button:hover i {
color: #636363;
}
i {
font-size: 50px;
color: gray;
}
/* Paper stack order */
#p1 {
z-index: 3;
}
#p2 {
z-index: 2;
}
#p3 {
z-index: 1;
}
<div id="book" class="book">
<div id="p1" class="paper">
<div class="front">
<div id="f1" class="front-content">
<h1>The Roman Empire was the post-Republican state of ancient Rome. It included territory around the Mediterranean in Europe, North Africa, and Western Asia, and was ruled by emperors. The adoption of Christianity as the state church in 380 and the
fall of the Western Roman Empire conventionally marks the end of classical antiquity and the beginning of the Middle Ages.</h1>
</div>
</div>
<div class="back">
<div id="b1" class="back-content">
<h1>The first two centuries of the Empire saw a period of unprecedented stability and prosperity known as the Pax Romana (lit. 'Roman Peace'). </h1>
</div>
</div>
</div>
<!-- Second page -->
<div id="p2" class="paper">
<div class="front">
<div id="f2" class="front-content">
<h1>Due to the Empire's extent and endurance, its institutions and culture had a lasting influence on the development of language, religion, art, architecture, literature, philosophy, law, and forms of government in its territories. Latin evolved
into the Romance languages, while Medieval Greek became the language of the East.</h1>
</div>
</div>
<div class="back">
<div id="b2" class="back-content">
<h1>he rediscovery of classical science and technology (which formed the basis for Islamic science) in medieval Europe led to the Scientific Renaissance and Scientific Revolution. Many modern legal systems, such as the Napoleonic Code, descend from
Roman law, while Rome's republican institutions have influenced the Italian city-state republics of the medieval period, the early United States, and modern democratic republics.
</h1>
</div>
</div>
</div>
</div>
Share
Improve this question
edited Aug 25, 2023 at 20:55
parsecer
asked Aug 24, 2023 at 21:09
parsecerparsecer
5,15020 gold badges86 silver badges167 bronze badges
3
- 1 Make absolute positioned div expand parent div height – isherwood Commented Aug 24, 2023 at 21:27
- 1 I'd look to create the effect without absolute positioning, though. Search results – isherwood Commented Aug 24, 2023 at 21:29
- 1 So basically the book height should be equal to the page with the max height, right? – Roko C. Buljan Commented Aug 25, 2023 at 9:57
3 Answers
Reset to default 8Animated flip-book using CSS
Z-index in 3D CSS is a painful, bug-prone approach and should be avoided. While going 3D, account for stacking context but forget about z-index.
Use translate
on the Z
axis instead.
- To create a flip-book where the tallest page dictates the entire book height — use CSS
flex
. - Retract (translate) each .page's
.back
to negative 100% X - Retract (translate) each .book's
.page
to negative pageIndex * 100% X - Now that all the pages are overlapping, stack each page in the Z axis by a negative amount of index times "thickness" pixels (not less than
0.4
px or the natural stacking order might transpare) - Use JavaScript purely to assign pages index var
--i
, and change CSS var--c
for current page index. The math for transformation and animation will be handled entirely by CSS.
Here's a Tl;Dr example, where I've inclined the .book
on the X axis just a bit, to make more obvious the way the pages animation actually works. For a pure top-down remove the rotate
rule.
PS: you can also click any page edge to flip more pages at once.
const flipBook = (elBook) => {
elBook.style.setProperty("--c", 0); // Set current page
elBook.querySelectorAll(".page").forEach((page, idx) => {
page.style.setProperty("--i", idx);
page.addEventListener("click", (evt) => {
const curr = evt.target.closest(".back") ? idx : idx + 1;
elBook.style.setProperty("--c", curr);
});
});
};
document.querySelectorAll(".book").forEach(flipBook);
* { box-sizing: border-box; }
body {
/* or any other parent wrapper */
margin: 0;
display: flex;
height: 100dvh;
perspective: 1000px;
font: 16px/1.4 sans-serif;
overflow: hidden;
background-color: #232425;
}
.book {
display: flex;
margin: auto;
width: 300px;
/*1* let pointer event go trough pages of lower Z than .book */
pointer-events: none;
transform-style: preserve-3d;
transition: translate 1s;
translate: calc(min(var(--c), 1) * 50%) 0%;
/* DEMO ONLY: incline on the X axis for pages preview */
rotate: 1 0 0 30deg;
}
.page {
--thickness: 5;
/* PS: Don't go below thickness 0.4 or the pages might transpare */
flex: none;
display: flex;
width: 100%;
/*1* allow pointer events on pages */
pointer-events: all;
user-select: none;
transform-style: preserve-3d;
border: 1px solid #0008;
transform-origin: left center;
transition:
transform 1s,
rotate 1s ease-in calc((min(var(--i), var(--c)) - max(var(--i), var(--c))) * 50ms);
translate: calc(var(--i) * -100%) 0px 0px;
transform: translateZ( calc((var(--c) - var(--i) - 0.5) * calc(var(--thickness) * 1px)));
rotate: 0 1 0 calc(clamp(0, var(--c) - var(--i), 1) * -180deg);
}
.page img {
width: 100%;
height: 100%;
object-fit: cover;
}
.front,
.back {
flex: none;
width: 100%;
padding: 2rem;
backface-visibility: hidden;
background-color: #fff;
/* Fix backface visibility Firefox: */
translate: 0px;
}
.back {
background-image: linear-gradient(to right, #fff 80%, #ddd 100%);
translate: -100% 0;
rotate: 0 1 0 180deg;
}
<div class="book">
<div class="page">
<div class="front">
<h1>FlipBook</h1>
<h3>2023.<br>Second edition</h3>
</div>
<div class="back">
<h2>Lorem Ipsum</h2>
1. Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi, modi, perspiciatis molestias cum neque delectus eum eveniet repellat iusto totam magnam cupiditate quaerat quis.
</div>
</div>
<div class="page">
<div class="front">
2. Dolor Molestias aspernatur repudiandae sed quos debitis recusandae consectetur ab facilis voluptates sint vero eos, consequuntur delectus?
</div>
<div class="back">
<img src="https://picsum.photos/500/400" alt="Img 1">
</div>
</div>
<div class="page">
<div class="front">
<h2>Sit amet</h2>
4. Consectetur adipisicing elit. Dignissimos illo voluptate sapiente provident tempore ea voluptates perferendis tenetur eos nulla, doloribus! Distinctio a nostrum ipsum, adipisci at mollitia.
</div>
<div class="back">
5. Debitis recusandae consectetur ab facilis voluptates sint vero eos, consequuntur delectus temporibus harum dolorem provident eaque perferendis.
</div>
</div>
<div class="page">
<div class="front">
<h2>Consectetur</h2>
6. Adipisicing elit. Sed, fuga aspernatur? Numquam, molestias unde! Voluptatibus sint aspernatur qui dolore est itaque ipsum consequuntur neque asperiores non obcaecati harum, perspiciatis voluptate!
</div>
<div class="back">
7. Temporibus, eum nobis? Adipisci, a? Eaque vel amet ut reprehenderit.
</div>
</div>
<div class="page">
<div class="front">
<img src="https://picsum.photos/536/354" alt="Img 2">
</div>
<div class="back">
<h3>Finalis</h3>
9. Lorem ipsum dolor sit, amet consectetur adipisicing elit. code by Roko, eniam vero, magni dignissimos deleniti hic ratione sequi ullam eos.
</div>
</div>
</div>
Tip:
For a pure HTML/CSS example see this similar answer of mine: Pure HTML/CSS3 animated flip-book
Tip:
If you want to create a navigation with buttons all you need to do is to change the "current page" CSS --c
var via JavaScript like:
// On navigation button click:
elBook.style.setProperty("--c", someIndex);
and the book will animate automagically to the desired page-view.
Git project: https://github./rokobuljan/flipbook
I think you should have done this using JavaScript. Calc every page height when the content is changed (you should get height of p1 div) and set it to height of book. You can get the height of content using this:
const book = document.getElementById('book');
... ... ...
book.style.height = element.querySelector('h1').offsetHeight;
The main thing is, update the book div's height when showing content changes.
If I understand your question correctly, you want the element to have a minimum height in px, but with the possibility to shrink when the content is larger.
To achive that, instead of using height
, set a minimum height.
min-height: 500px;
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744629932a4584796.html
评论列表(0条)