Приложение для чтения - пример html js css



Книга Приложение для чтения



Приложение для чтения (HTML код)



<div class="container">

<div class="status-bar">

<span class="status-bar__clock" onload="showTime()"></span>

<div>

<img class="status-bar__img img" src="https://utopian-drink.surge.sh/images/icon/status-bar.svg" alt="status-bar">

</div>

</div>

<header class="header">

<div class="header__context">

<h1 class="header__title">browse</h1>
<b class="header__text">recommended</b>

</div>

<nav class="tabbar">

<ul class="tabbar__list list">

<li class="tabbar__item">history</li>
<li class="tabbar__item">classical</li>
<li class="tabbar__item active">biography</li>
<li class="tabbar__item">cartoon</li>
<li class="tabbar__item">fantasy</li>
<li class="tabbar__item">drama</li>
<li class="tabbar__item">memoir</li>
<li class="tabbar__item">self help</li>

</ul>

</nav>

</header>

<div class="global-button global-button--position-ab flex">

<button class="global-button__back">

<img class="img" src="https://utopian-drink.surge.sh/images/icon/back.svg" alt="icon-back">

</button>

<button>

<img class="img" src="https://utopian-drink.surge.sh/images/icon/menu.svg" alt="icon-menu">

</button>

</div>

<main class="main">

<ul class="product-card list"></ul>

</main>

</div>



Приложение для чтения (CSS код)




@import url('https://fonts.googleapis.com/css2?family=Kumbh+Sans&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Rubik&display=swap');

html {

box-sizing: border-box ;
--padding-left: 1.25em ;
--duration-header: .25s ;
--duration-product-item: .5s ;

}

html *,
html *::before,
html *::after {

box-sizing: inherit ;
scrollbar-width: none ;
}

@media (max-width: 26.875em) {

html {

--none: none ;
--top-start: 4.99em ;
--top-end: 2.08em ;
}

}

body{

margin: 0 ;
display: flex ;
user-select: none ;
align-items: center ;
justify-content: center ;
background-color: #dadfea ;
font-family: 'Kumbh Sans', sans-serif ;
-webkit-tap-highlight-color: transparent ;

}

::-webkit-scrollbar{

width: 0 ;
height: 0 ;

}

.list {

margin: 0 ;
padding: 0 ;
list-style-type: none ;

}

.img {

width: 100% ;
display: block ;
object-fit: cover ;
position: relative ;

}

.img::after{

top: 0 ;
left: 0 ;
content: "" ;
width: 100% ;
height: 100% ;
position: absolute ;
background-color: white ;

}

.flex {

display: flex ;
align-items: center ;
justify-content: space-between ;

}

button {

all: unset ;
font: inherit ;
cursor: pointer ;

}

.container {

width: 100% ;
height: 100% ;
display: flex ;
overflow: hidden ;
font-size: 6.4vw ;
position: relative ;
flex-direction: column ;
background-color: white ;
border-radius: var(--none, 1.3em ) ;
border: var(--none, 0.45em solid black) ;

}

.container::before {

right: 0 ;
bottom: 0 ;
opacity: 0 ;
content: " " ;
position: absolute ;
pointer-events: none ;
transition: opacity .2s ;
height: calc(100% - 4.81em) ;
background-color: #f8f9fc ;
width: calc(100% - var(--padding-left)) ;

}

@media (min-width: 26.875em) {

.container {

font-size: 1em ;
width: 15.0375em ;
height: 31.84em ;

}

.container::before {

height: 80.2% ;


}

}


.container.active::before{

opacity: 1 ;
z-index: 100 ;

}

.status-bar {

display: var(--none, flex) ;
padding: .3em .25em 0 .95em ;
justify-content: space-between ;


}

.status-bar__clock {

font-size: .53em ;
font-weight: bold ;
letter-spacing: .075em ;
font-family: 'Rubik', sans-serif ;

}

.status-bar__img {

width: 2.85em ;

}

.header {

padding: 1.15em 0 .25em var(--padding-left) ;
transition: height, var(--duration-header), padding var(--duration-header), transform var(--duration-header), opacity var(--duration-header);

}

.header.hide {

height: 0 ;
opacity: 0 ;
padding-top: 0 ;
padding-bottom: 0 ;
pointer-events: none ;
transform: translate3d(0, -5%, 0) ;

}

.header__context {

display: flex ;
font-size: .6em ;
align-items: baseline ;
text-transform: capitalize ;

}

.header__title {

margin: 0 .8em 0 0 ;
letter-spacing: 0.03em ;

}

.header__text {

color: #414141b4 ;

}

.tabbar {

overflow: hidden ;

}

.tabbar__list {

overflow: auto ;
cursor: pointer ;
white-space: nowrap ;
padding: .6em 1.2em .6em 0 ;


}

.tabbar__item {

font-size: .41em ;
color: #9e9fa2 ;
border-radius: 2em ;
display: inline-flex ;
justify-content: center ;
padding: .75em 1.2em .4em ;
text-transform: capitalize ;
background-color: #f0f1f4 ;
pointer-events: var(--pointer-event) ;

}

.tabbar__item:not(:first-of-type) {

margin-left: .5em ;

}

.tabbar__item.active {

color: #f1f1f1 ;
background-color: #1469fc ;

}

.global-button {

opacity: 0 ;
width: 100% ;
pointer-events: none ;
padding: .55em 1em 0 .8em ;

}

.global-button--position-ab {

top: .5% ;
position: absolute ;

}

@media (min-width: 26.875em) {

.global-button--position-ab {

top: 4.6% ;

}

}


.global-button > * {

width: 1em ;
height: 1em ;

}

.global-button.show {

opacity: 1 ;
pointer-events: initial ;

}

.main {

height: 100% ;
font-size: 1.1em ;
touch-action: none ;
overflow: hidden auto ;
overscroll-behavior: contain ;

}

@media (min-width: 26.875em) {

.main {

font-size: 1em ;

}

}

.product-card {

height: var(--productCardHeight) ;
padding-left: var(--padding-left) ;

}

.product-card__item {

width: 100% ;
display: flex ;
height: 9.92em ;
align-items: center ;
max-height: var(--max-height-item) ;
pointer-events: var(--pointer-event) ;
transform: var(--transform, perspective(1000px) rotateX(0)) ;
transition: height var(--duration-product-item), margin var(--timeOut, calc( var(--duration-product-item) / 1.5 )) ;

}

.product-card__img {

width: 6.55em ;
height: 8.75em ;
overflow: hidden ;
position: absolute ;
border-radius: .3em ;
pointer-events: none ;
transform: translate3d(80%, 0, 0) ;
transition: border-radius var(--duration-product-item) ;
box-shadow: 0.3125em 0.3125em 0.875em -0.1875em #403e3e4f ;

}

.product-card__item.active {

height: 100% ;
padding-top: 3em ;
align-items: unset ;
margin-bottom: 1.5em ;
flex-direction: column ;

}

@media (min-width: 26.875em) {

.product-card__item.active {

padding-top: 3.55em ;

}

}


.product-card__item.active .product-card__img {

z-index: 200 ;
cursor: pointer ;
pointer-events: initial ;

}

.product-card__img.move-img {

border-radius: 0 .3em .3em 0 ;
animation: product-card-img-move var(--duration-product-item) forwards ;

}

@keyframes product-card-img-move {

0%, 20%{

top: var(--top-start, 20.5%) ;

}

80% ,100%{

top: var(--top-end, 12.8%) ;
transform: translate3d(-20%, 0, 0);

}

}

.product-card__img.back-img {

border-radius: .3em ;
animation: product-card-img-back var(--duration-product-item) forwards ;

}

@keyframes product-card-img-back {

0%, 15%{

top: var(--top-end, 12.8%) ;
transform: translate3d(-20%, 0, 0);

}

50% ,100%{

top: var(--top-start, 20.5%) ;

}


}

.product-card__content {

width: 6em ;
z-index: 50 ;
height: 6.88em ;
cursor: pointer ;
overflow: hidden ;
border-radius: .25em ;
will-change : transform ;
background-color: white ;
text-transform: capitalize ;
box-shadow: -2px 6px 15px 0px #2f2f2f24 ;
transition: opacity calc(var(--duration-product-item) / 2) ;

}

.product-card__content.open-content {

width: 100% ;
height: 100% ;
z-index: 150 ;
cursor: initial ;
box-shadow: none ;
padding-left: 1.05em ;
pointer-events: initial ;
background-color: unset ;
transform: translate3d(0, 180%, 0) ;
animation: open-content var(--duration-product-item) forwards,
opacity-content calc(var(--duration-product-item) * 2) forwards ;

}

@keyframes open-content {

100%{

transform: none ;

}

}

@keyframes opacity-content {

0%{

opacity: 0;
}

100%{

opacity: 1;


}

}

.product-card__info {

padding: .82em .7em ;

}

.product-card__content.open-content .product-card__info {

width: 63% ;
margin-left: auto ;
padding: .8em .7em ;

}

.product-card__product-name {

margin: 0 0 .2em ;
line-height: 1.4 ;
font-size: .63em ;
min-height: 2.778em ;
white-space: pre-line ;

}

.product-card__content.open-content .product-card__product-name {

font-size: .78em ;
line-height: 1.5 ;
margin-bottom: .8em ;
letter-spacing: .03em ;

}

.product-card__product-author {

font-size: .4em ;
font-weight: bold ;
color: #00000073 ;
letter-spacing: -.01em ;

}

.product-card__content.open-content .product-card__product-author {

font-size: .55em ;

}

.product-card__rank {

display: flex ;
align-items: center ;
margin: .8em 0 .75em ;

}

.product-card__content.open-content .product-card__rank {

width: 0 ;
overflow: hidden ;
margin: 1.2em 0 0 ;
animation: show-rank var(--duration-product-item) var(--duration-product-item) forwards ;

}

@keyframes show-rank {

100%{

width: 100% ;

}

}

.product-card__starts {

position: relative ;

}

.product-card__starts::after {

right: 0 ;
content: "" ;
height: 100% ;
width: var(--rank) ;
position: absolute ;
background-color: #ffffffc2 ;

}

.product-card__content.open-content .product-card__starts::after {

background-color: #f8f9fcc9 ;

}

.product-card__start-icon {

width: .5em ;
height: .5em ;
flex-shrink: 0 ;
margin-right: .1em ;

}

.product-card__content.open-content .product-card__start-icon {

animation: show-star var(--duration-product-item) var(--duration-product-item) forwards ;

}

@keyframes show-star {

0% {

transform: scale(0) ;

}

100%{

transform: scale(1) ;

}

}

.product-card__rank-number {

font-size: .5em ;
color: #ffb964 ;
font-weight: bold ;
margin-left: .15em ;
margin-bottom: -.3em ;
letter-spacing: .05em ;

}

.product-card__view {

display: flex ;
font-size: .45em ;
font-weight: bold ;
color: #00000059 ;
position: relative ;
align-items: center ;

}

.product-card__view.hide{

display: none ;

}

.product-card__view::after {

right: 4% ;
opacity: .2 ;
width: 1.6em ;
content: " " ;
height: 1.6em ;
position: absolute ;
transform: rotate(180deg) ;
background-position: center ;
background-repeat: no-repeat ;
background-image: url(http://utopian-drink.surge.sh/images/icon/back.svg) ;

}

.product-card__view-number {

color: #408cff ;
margin-right: .45em ;

}

.product-card__view-value{

font-size: .45em ;
color:#00000059 ;
margin: 0 0 -.3em .8em ;

}

.product-card__view-value.hide{

display: none ;

}

.product-card__buttons {

width: 100% ;
margin-top: 2.8em ;
font-size: 0.45em ;
color: #000000d9 ;
will-change: transform ;
padding: 0 1.6em 2.4em 0 ;
border-bottom: .2em solid #c3c3c31f ;

}

@media (max-width: 26.875em) {

.product-card__buttons {

margin-top: 1.8em ;
padding: 0 1.6em 1.4em 0 ;

}

}

.product-card__button-icon {

width: 1.6em ;
margin-right: .8em ;

}

.product-card__button-text {

margin: .5em 0 0 ;

}

.product-card__context {

height: 100% ;
overflow: hidden ;
font-size: .52em ;
padding: 1.2em 0 0 ;
text-transform: none ;

}

.product-card__context ::first-letter{

text-transform: capitalize ;

}

.product-card__description {

overflow: auto ;
line-height: 1.9 ;
margin: 1.6em 0 0 ;
color: #969696a8 ;
padding-right: 2.15em ;
pointer-events: initial ;
height: calc(100% - 23.2em) ;

}

@media (min-width: 26.875em) {

.product-card__description {

overflow: hidden ;

}

}

.product-card__content.open-content .product-card__description {

transform: translate3d(0, 12%, 0) ;
animation: description var(--duration-product-item) calc(var(--duration-product-item) / 2) forwards;

}

@keyframes description {

100% {

transform: translate3d(0, 0, 0) ;

}

}

.product-card__cta {

opacity: 0 ;
z-index: 300 ;
color: white ;
font-size: .55em ;
margin-left: auto ;
pointer-events: none ;
letter-spacing: 0.1em ;
text-transform: capitalize ;
background-color: #1368fa ;
padding: 1.7em 1.5em 1em 1.9em ;

}

.product-card__item.active .product-card__cta {

opacity: 1 ;
pointer-events: initial ;
transition: opacity calc(var(--duration-product-item) / 2) var(--duration-product-item) ;

}


Приложение для чтения (JS код)




// Designed by: Crank
// Original image: https://dribbble.com/shots/5707503-Reading-Application?utm_source=Pinterest_Shot&utm_campaign=crankwh&utm_content=Reading%20Application&utm_medium=Social_Share

"use strict";

gsap.registerPlugin(ScrollTrigger);

let info;
let genre;
const request = "https://www.json-generator.com/api/json/get/cqyGXnDfjC?indent=2";
const html = document.documentElement;
const container = document.querySelector(".container");
const tabbarList = document.querySelector(".tabbar__list");
const main = container.querySelector(".main");
const productCard = main.querySelector(".product-card");
let productCardItems;
const header = document.querySelector(".header");
const time = parseFloat(getComputedStyle(document.documentElement).getPropertyValue("--duration-header")) * 1000;
const globalButton = document.querySelector(".global-button");
const globalButtonBack = globalButton.querySelector(".global-button__back");
let elements;
let activeItem;
let isMove = false;
let startY;
let scrollTop;
let startX;
let scrollLeft;
let tabbarItemActive = tabbarList.querySelector(".tabbar__item.active");
const statusBar = document.querySelector(".status-bar");
const statusBarClock = document.querySelector(".status-bar__clock");
let progressScroll = 0;
let notScroll = false;

fetch(request).
then(response => response.json()).
then(item => {
info = item;
booksGenre(info);
setMaxHeight();
});

function setMaxHeight() {

document.body.style.height = window.innerHeight + "px";
const maxHeightItem = container.clientHeight - globalButton.offsetHeight - statusBar.offsetHeight;
html.style.setProperty("--max-height-item", `${maxHeightItem}px`);
html.style.setProperty("--height-body", `${window.innerHeight}px`);
}

function booksGenre(info) {

const key = tabbarItemActive.textContent;
genre = info[key];

if (!genre) return;
productCard.innerHTML = "";
genre.forEach(book => {

book.rank = `${book.rank}`.replace(/^\d$/, "$&.0");
const width = 100 - book.rank * 20;

book.keywords.forEach(word => {

const regex = new RegExp(`${word}`, `i`);
book.description = book.description.replace(regex, `${word}`);

});

productCard.insertAdjacentHTML("beforeend", creatBook(book, width));

});

productCardItems = Array.from(productCard.children);
const productCardHeight = (genre.length + 3) * productCard.firstElementChild.offsetHeight;
html.style.setProperty("--productCardHeight", `${productCardHeight}px`);

main.scrollTop = 0;

ScrollTrigger.getAll().forEach(item => {
item.kill();
});

roll(productCardItems);

}

function creatBook(book, width) {

const { picture, name, author, rank, view, description } = book;

return `



  • book






    ${name}



    ${author}






    star-icon
    star-icon
    star-icon
    star-icon
    star-icon



    ${rank}
    (${view})





    ${view}


    views



















    about the book


    ${description}









  • `;
    }

    function openProductCard(e, productCardItems) {

    const target = e.target;
    activeItem = target.closest(".product-card__item");

    if (target.closest(".product-card__img")) {
    activeItem.classList.remove("active");
    closeProductCard(elements);
    return;

    }

    if (!target.closest(".product-card__content")) return;

    const indexActiveItem = productCardItems.findIndex(item => item == activeItem);
    notScroll = true;
    main.scrollTo(0, indexActiveItem * productCardItems[0].offsetHeight);
    const productCardWrapperImg = activeItem.querySelector(".product-card__img");
    const productCardContent = activeItem.querySelector(".product-card__content");
    const productCardView = productCardContent.querySelector(".product-card__view");
    const productCardViewValue = productCardContent.querySelector(".product-card__view-value");

    elements = [
    activeItem,
    productCardWrapperImg,
    productCardContent,
    productCard,
    header,
    container,
    productCardView,
    productCardViewValue];


    header.classList.add("hide");

    if (header.classList.contains("hide")) {

    productCard.style.paddingTop = `${globalButton.offsetHeight}px`;

    }

    activeItem.style.cssText = `
    --timeOut : 0s;
    --transform : none;

    `;

    main.style.cssText = `
    pointer-events : none;
    overflow: hidden;

    `;

    container.classList.add("active");
    productCardView.classList.add("hide");
    productCardViewValue.classList.remove("hide");

    productCardContent.classList.add("open-content");
    productCardWrapperImg.classList.add("move-img");

    activeItem.classList.add("active");


    }



    function closeProductCard(elements) {

    const [
    activeItem,
    productCardWrapperImg,
    productCardContent,
    productCard,
    header,
    container,
    productCardView,
    productCardViewValue] =
    elements;

    if (!activeItem.classList.contains("active")) {

    productCardWrapperImg.classList.add("back-img");
    productCardContent.classList.remove("open-content");
    container.classList.remove("active");
    productCardView.classList.remove("hide");
    productCardViewValue.classList.add("hide");
    productCardContent.style.opacity = 0;

    setTimeout(() => {
    productCard.style = "";
    header.classList.remove("hide");
    }, time);

    }

    productCardWrapperImg.addEventListener("animationend", function (e) {

    if (e.animationName.includes("img-back")) {
    productCardItems.forEach(item => {
    item.style.removeProperty("--timeOut");
    item.classList.remove("hide");
    });

    this.classList.remove("move-img", "back-img");
    productCardContent.style = "";
    main.style = "";
    activeItem.style = "";

    }

    });


    }

    function showTime() {
    const date = new Date();
    let hours = date.getHours();
    let minutes = date.getMinutes();

    if (hours == 0) {
    hours = 12;
    }

    if (hours > 12) {
    hours = hours - 12;
    }

    hours = hours < 10 ? "0" + hours : hours;
    minutes = minutes < 10 ? "0" + minutes : minutes;

    statusBarClock.textContent = `${hours}:${minutes}`;
    setTimeout(showTime, 1000);
    };

    showTime();

    tabbarList.addEventListener("click", function (e) {

    if (tabbarItemActive == e.target) return;

    if (e.target.tagName != "LI") return;

    tabbarItemActive = e.target;
    booksGenre(info);

    if (!genre) return;

    tabbarItemActive.classList.add("active");


    gsap.to(".product-card__content", {
    duration: .4,
    rotationY: -180,
    scaleX: -1 });


    gsap.fromTo(".product-card__img",
    { duration: .75, filter: "brightness(.5)" },
    { duration: .75, filter: "brightness(1)" });

    gsap.to(".product-card__content", { clearProps: "all" });

    tabbarList.querySelectorAll(".tabbar__item").forEach(item => {

    if (item != tabbarItemActive) {
    item.classList.remove("active");
    }

    });

    });

    tabbarList.addEventListener("pointerdown", function (e) {


    isMove = true;
    startX = Math.floor(e.pageX - this.getBoundingClientRect().left);
    scrollLeft = this.scrollLeft;

    });

    tabbarList.addEventListener("pointermove", function (e) {

    if (!isMove) return;

    this.style.cssText = `
    --pointer-event: none;
    cursor : grabbing;

    `;
    const lastX = Math.floor(e.pageX - this.getBoundingClientRect().left);
    const walk = lastX - startX;
    this.scrollLeft = scrollLeft - walk;

    });

    tabbarList.addEventListener("pointerup", function () {
    isMove = false;
    this.style = "";

    });

    tabbarList.addEventListener("pointerleave", function () {
    isMove = false;
    this.style = "";

    });

    header.addEventListener("transitionend", function () {

    if (this.classList.contains("hide")) {

    globalButton.classList.add("show");

    }

    });

    header.addEventListener("transitionstart", () => {
    globalButton.classList.remove("show");

    });

    globalButtonBack.addEventListener("click", () => {
    activeItem.classList.remove("active");
    closeProductCard(elements);

    });

    productCard.addEventListener("click", e => openProductCard(e, productCardItems));

    function roll(productCardItems) {

    productCardItems.forEach((item, index) => {

    gsap.set(item, { transformPerspective: 1000 });

    const animation = gsap.to(item, {

    rotationX: 95,
    y: 70,
    opacity: 0 });



    ScrollTrigger.create({

    animation: animation,
    trigger: item,
    scroller: main,
    start: `top+=5 top`,
    end: `bottom-=5 top`,
    scrub: true,

    onEnter: progress => {
    progressScroll = progress.end + 5;
    },

    onLeaveBack: progress => {
    progressScroll = progress.start - 5;
    },

    onEnterBack: progress => {
    progressScroll = progress.start - 5;
    },

    onUpdate: ({ direction, isActive }) => {

    productCardItems.forEach(item => {

    if (index == productCardItems.length - 1) return;

    if (isActive) item.style.marginBottom = direction * .25 + "em";else
    item.style.removeProperty("margin-bottom");

    });

    } });


    });


    }


    function scrollInMain() {

    if (notScroll) return;

    main.scroll({
    top: progressScroll,
    behavior: "smooth" });


    }

    main.addEventListener("pointerdown", function (e) {

    if (activeItem && activeItem.classList.contains("active")) return;

    isMove = true;
    startY = Math.floor(e.pageY - this.getBoundingClientRect().top);
    scrollTop = this.scrollTop;

    });

    main.addEventListener("pointermove", function (e) {

    if (!isMove) return;

    notScroll = false;
    const lastY = Math.floor(e.pageY - this.getBoundingClientRect().top);
    const walk = lastY - startY;
    this.scrollTop = scrollTop - walk;
    this.style.setProperty("--pointer-event", "none");

    });

    main.addEventListener("pointerup", function () {

    isMove = false;
    this.style.removeProperty("--pointer-event");
    scrollInMain();

    });

    main.addEventListener("pointerleave", function () {
    isMove = false;
    this.style.removeProperty("--pointer-event");

    });

    window.addEventListener("resize", setMaxHeight);

    document.ondragstart = () => {
    return false;
    };
    //# sourceURL=pen.js


    Приложение для чтения (Результат кода)


    714   0  

    Comments

      Ничего не найдено.