Merge pull request #48 from KevinMidboe/refactor/image-loading
Refactor/image loading
This commit is contained in:
		| @@ -2,28 +2,32 @@ | ||||
|   <section class="movie"> | ||||
|  | ||||
|     <!-- HEADER w/ POSTER --> | ||||
|     <header class="movie__header" :style="{ 'background-image': movie && backdrop !== null ? 'url(' + ASSET_URL + ASSET_SIZES[1] + backdrop + ')' : '' }" :class="compact ? 'compact' : ''" @click="compact=!compact"> | ||||
|       <div class="movie__wrap movie__wrap--header"> | ||||
|         <figure class="movie__poster"> | ||||
|     <header ref="header" :class="compact ? 'compact' : ''" @click="compact=!compact"> | ||||
|       <figure class="movie__poster"> | ||||
|         <img class="movie-item__img is-loaded" | ||||
|              ref="poster-image" | ||||
|              src="~assets/placeholder.png"> | ||||
|  | ||||
|         <!--   --> | ||||
|         <!-- <img v-else class="movie-item__img is-loaded" src="~assets/no-image.png" ref="image" alt="No image - linked image unavailable"> --> | ||||
|       </figure> | ||||
| <!--         <figure class="movie__poster"> | ||||
|           <img v-if="movie && poster === null" | ||||
|             class="movies-item__img is-loaded" | ||||
|             alt="movie poster image" | ||||
|             src="~assets/no-image.png"> | ||||
|           <img v-else-if="poster === undefined" | ||||
|             class="movies-item__img grey" | ||||
|             alt="movie poster image"> | ||||
|             <!-- src="~assets/placeholder.png"> --> | ||||
|             alt="movie poster image" | ||||
|             src="~assets/placeholder.png"> | ||||
|           <img v-else | ||||
|             class="movies-item__img is-loaded" | ||||
|             alt="movie poster image" | ||||
|             :src="ASSET_URL + ASSET_SIZES[0] + poster"> | ||||
|         </figure> | ||||
|         </figure> --> | ||||
|  | ||||
|         <div class="movie__title"> | ||||
|           <h1 v-if="movie">{{ movie.title }}</h1> | ||||
|           <loading-placeholder v-else :count="1" /> | ||||
|         </div> | ||||
|       </div> | ||||
|         <h1 class="movie__title" v-if="movie">{{ movie.title }}</h1> | ||||
|         <loading-placeholder v-else :count="1" /> | ||||
|     </header> | ||||
|  | ||||
|     <!-- Siderbar and movie info --> | ||||
| @@ -64,32 +68,48 @@ | ||||
|  | ||||
|         <!-- MOVIE INFO --> | ||||
|         <div class="movie__info"> | ||||
|           <div class="movie__description" v-if="movie"> {{ movie.overview }}</div> | ||||
|  | ||||
|           <!-- Loading placeholder --> | ||||
|           <div class="movie__description noselect" | ||||
|                @click="truncatedDescription=!truncatedDescription" | ||||
|                v-if="!loading"> | ||||
|             <span :class="truncatedDescription ? 'truncated':null">{{ movie.overview }}</span> | ||||
|             <button class="truncate-toggle"><i>⬆</i></button> | ||||
|           </div> | ||||
|           <div v-else class="movie__description"> | ||||
|             <loading-placeholder :count="12" /> | ||||
|             <loading-placeholder :count="5" /> | ||||
|           </div> | ||||
|  | ||||
|           <div class="movie__details" v-if="movie"> | ||||
|             <div v-if="movie.year" class="movie__details-block"> | ||||
|               <h2 class="movie__details-title">Release Date</h2> | ||||
|               <div class="movie__details-text">{{ movie.year }}</div> | ||||
|             <div v-if="movie.year"> | ||||
|               <h2 class="title">Release Date</h2> | ||||
|               <div class="text">{{ movie.year }}</div> | ||||
|             </div> | ||||
|  | ||||
|              <div v-if="movie.rank" class="movie__details-block"> | ||||
|               <h2 class="movie__details-title">Rating</h2> | ||||
|               <div class="movie__details-text">{{ movie.rank }}</div> | ||||
|              <div v-if="movie.rating"> | ||||
|               <h2 class="title">Rating</h2> | ||||
|               <div class="text">{{ movie.rating }}</div> | ||||
|             </div> | ||||
|  | ||||
|             <div v-if="movie.type == 'show'" class="movie__details-block"> | ||||
|               <h2 class="movie__details-title">Seasons</h2> | ||||
|               <div class="movie__details-text">{{ movie.seasons }}</div> | ||||
|             <div v-if="movie.type == 'show'"> | ||||
|               <h2 class="title">Seasons</h2> | ||||
|               <div class="text">{{ movie.seasons }}</div> | ||||
|             </div> | ||||
|  | ||||
|             <div v-if="movie.genres" class="movie__details-block"> | ||||
|               <h2 class="movie__details-title">Genres</h2> | ||||
|               <div class="movie__details-text">{{ nestedDataToString(movie.genres) }}</div> | ||||
|             <div v-if="movie.genres"> | ||||
|               <h2 class="title">Genres</h2> | ||||
|               <div class="text">{{ movie.genres.join(', ') }}</div> | ||||
|             </div> | ||||
|  | ||||
|             <div v-if="movie.type == 'show'"> | ||||
|               <h2 class="title">Production status</h2> | ||||
|               <div class="text">{{ movie.production_status }}</div> | ||||
|             </div> | ||||
|  | ||||
|  | ||||
|             <div v-if="movie.type == 'show'"> | ||||
|               <h2 class="title">Runtime</h2> | ||||
|               <div class="text">{{ movie.runtime[0] }} minutes</div> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
| @@ -126,7 +146,17 @@ import LoadingPlaceholder from './ui/LoadingPlaceholder' | ||||
| import { getMovie, getPerson, getShow, request, getRequestStatus } from '@/api' | ||||
|  | ||||
| export default { | ||||
|   props: ['id', 'type'], | ||||
|   // props: ['id', 'type'], | ||||
|   props: { | ||||
|     id: { | ||||
|       required: true, | ||||
|       type: Number | ||||
|     }, | ||||
|     type: { | ||||
|       required: false, | ||||
|       type: String | ||||
|     } | ||||
|   }, | ||||
|   components: { TorrentList, Person, LoadingPlaceholder, SidebarListElement }, | ||||
|   directives: { img: img }, // TODO decide to remove or use | ||||
|   data(){ | ||||
| @@ -142,11 +172,40 @@ export default { | ||||
|       requested: false, | ||||
|       admin: localStorage.getItem('admin') == "true" ? true : false, | ||||
|       showTorrents: false, | ||||
|       compact: false | ||||
|       compact: false, | ||||
|       loading: true, | ||||
|       truncatedDescription: true | ||||
|     } | ||||
|   }, | ||||
|   watch: { | ||||
|     id: function(val){ | ||||
|       if (this.type === 'movie') { | ||||
|         this.fetchMovie(val); | ||||
|       } else { | ||||
|         this.fetchShow(val) | ||||
|       } | ||||
|     }, | ||||
|     backdrop: function(backdrop) { | ||||
|       if (backdrop != null) { | ||||
|         const style = { | ||||
|           backgroundImage: 'url(' + this.ASSET_URL + this.ASSET_SIZES[1] + backdrop + ')' | ||||
|         } | ||||
|  | ||||
|         Object.assign(this.$refs.header.style, style) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     numberOfTorrentResults: () => { | ||||
|       let numTorrents = store.getters['torrentModule/resultCount'] | ||||
|       return numTorrents !== null ? numTorrents + ' results' : null | ||||
|     } | ||||
|   }, | ||||
|   methods: { | ||||
|     parseResponse(movie) { | ||||
|       setTimeout(() => { | ||||
|  | ||||
|       this.loading = false | ||||
|       this.movie = { ...movie } | ||||
|       this.title = movie.title | ||||
|       this.poster = movie.poster | ||||
| @@ -155,13 +214,22 @@ export default { | ||||
|       this.checkIfRequested(movie) | ||||
|         .then(status => this.requested = status) | ||||
|  | ||||
|  | ||||
|       store.dispatch('documentTitle/updateTitle', movie.title) | ||||
|       this.setPosterSrc() | ||||
|       }, 1000) | ||||
|     }, | ||||
|     async checkIfRequested(movie) { | ||||
|       return await getRequestStatus(movie.id, movie.type) | ||||
|     }, | ||||
|     nestedDataToString(data) { | ||||
|       return data.join(', ') | ||||
|     setPosterSrc() { | ||||
|       const poster = this.$refs['poster-image'] | ||||
|       if (this.poster == null) { | ||||
|         poster.src = '/dist/no-image.png' | ||||
|         return | ||||
|       } | ||||
|  | ||||
|       poster.src = `${this.ASSET_URL}${this.ASSET_SIZES[0]}${this.poster}` | ||||
|     }, | ||||
|     sendRequest(){ | ||||
|       request(this.id, this.type, storage.token) | ||||
| @@ -176,25 +244,7 @@ export default { | ||||
|       window.location.href = 'https://www.themoviedb.org/' + tmdbType + '/' + this.id | ||||
|     }, | ||||
|   }, | ||||
|   watch: { | ||||
|     id: function(val){ | ||||
|       if (this.type === 'movie') { | ||||
|         this.fetchMovie(val); | ||||
|       } else { | ||||
|         this.fetchShow(val) | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     numberOfTorrentResults: () => { | ||||
|       let numTorrents = store.getters['torrentModule/resultCount'] | ||||
|       return numTorrents !== null ? numTorrents + ' results' : null | ||||
|     } | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     store.dispatch('documentTitle/updateTitle', this.prevDocumentTitle) | ||||
|   }, | ||||
|   created(){ | ||||
|   created() { | ||||
|     this.prevDocumentTitle = store.getters['documentTitle/title'] | ||||
|  | ||||
|     if (this.type === 'movie') { | ||||
| @@ -216,8 +266,9 @@ export default { | ||||
|           this.$router.push({ name: '404' }); | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     console.log('admin: ', this.admin) | ||||
|   }, | ||||
|   beforeDestroy() { | ||||
|     store.dispatch('documentTitle/updateTitle', this.prevDocumentTitle) | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @@ -226,6 +277,89 @@ export default { | ||||
| @import "./src/scss/loading-placeholder"; | ||||
| @import "./src/scss/variables"; | ||||
| @import "./src/scss/media-queries"; | ||||
| @import "./src/scss/main"; | ||||
|  | ||||
| header { | ||||
|   $duration: 0.2s; | ||||
|   height: 250px; | ||||
|   transform: scaleY(1); | ||||
|   transition: height $duration ease; | ||||
|   transform-origin: top; | ||||
|   position: relative; | ||||
|   background-size: cover; | ||||
|   background-repeat: no-repeat; | ||||
|   background-position: 50% 50%; | ||||
|   background-color: $background-color; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|  | ||||
|   @include tablet-min { | ||||
|     height: 350px; | ||||
|   } | ||||
|   &:before { | ||||
|     content: ""; | ||||
|     display: block; | ||||
|     position: absolute; | ||||
|     top: 0; | ||||
|     left: 0; | ||||
|     z-index: 0; | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     background: $background-dark-85; | ||||
|   } | ||||
|   @include mobile { | ||||
|     &.compact { | ||||
|       height: 100px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .movie__poster { | ||||
|   display: none; | ||||
|  | ||||
|   @include desktop { | ||||
|     background: $background-color; | ||||
|     height: 0; | ||||
|     display: block; | ||||
|     position: absolute; | ||||
|     width: calc(45% - 40px); | ||||
|     top: 40px; | ||||
|     left: 40px; | ||||
|  | ||||
|     > img { | ||||
|       width: 100%; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| .truncate-toggle { | ||||
|   border: none; | ||||
|   background: none; | ||||
|   width: 100%; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   text-align: center; | ||||
|   color: $text-color; | ||||
|  | ||||
|   > i { | ||||
|     font-style: unset; | ||||
|     font-size: 0.7rem; | ||||
|     transition: 0.3s ease all; | ||||
|     transform: rotateY(180deg) | ||||
|   } | ||||
|  | ||||
|   &::before, &::after { | ||||
|     content: ''; | ||||
|     flex: 1; | ||||
|     border-bottom: 1px solid $text-color-50; | ||||
|   } | ||||
|   &::before { | ||||
|       margin-right: 1rem; | ||||
|   } | ||||
|   &::after { | ||||
|       margin-left: 1rem; | ||||
|   } | ||||
| } | ||||
|  | ||||
| .movie { | ||||
|   &__wrap { | ||||
| @@ -246,49 +380,6 @@ export default { | ||||
|       color: $text-color; | ||||
|     } | ||||
|   } | ||||
|   &__header { | ||||
|     $duration: 0.2s; | ||||
|     height: 250px; | ||||
|     transform: scaleY(1); | ||||
|     transition: height $duration ease; | ||||
|     transform-origin: top; | ||||
|     position: relative; | ||||
|     background-size: cover; | ||||
|     background-repeat: no-repeat; | ||||
|     background-position: 50% 50%; | ||||
|     background-color: $background-color; | ||||
|     @include tablet-min { | ||||
|       height: 350px; | ||||
|     } | ||||
|     &:before { | ||||
|       content: ""; | ||||
|       display: block; | ||||
|       position: absolute; | ||||
|       top: 0; | ||||
|       left: 0; | ||||
|       z-index: 0; | ||||
|       width: 100%; | ||||
|       height: 100%; | ||||
|       background: $background-dark-85; | ||||
|     } | ||||
|     &.compact { | ||||
|       height: 100px; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &__poster { | ||||
|     display: none; | ||||
|     @include tablet-min { | ||||
|       background: $background-color; | ||||
|       height: 0; | ||||
|       display: block; | ||||
|       position: absolute; | ||||
|       width: calc(45% - 40px); | ||||
|       top: 40px; | ||||
|       left: 40px; | ||||
|  | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   &__img { | ||||
|     display: block; | ||||
| @@ -364,37 +455,49 @@ export default { | ||||
|       font-size: 13px; | ||||
|       line-height: 1.8; | ||||
|       margin-bottom: 20px; | ||||
|  | ||||
|       & .truncated { | ||||
|         display: -webkit-box; | ||||
|         overflow: hidden; | ||||
|         -webkit-line-clamp: 4; | ||||
|         -webkit-box-orient: vertical; | ||||
|  | ||||
|         & + .truncate-toggle > i { | ||||
|           transform: rotateY(0deg) rotateZ(180deg); | ||||
|         }  | ||||
|       } | ||||
|  | ||||
|       @include tablet-min { | ||||
|         margin-bottom: 30px; | ||||
|         font-size: 14px; | ||||
|       } | ||||
|     } | ||||
|     &__details { | ||||
|       &-block { | ||||
|         float: left; | ||||
|       } | ||||
|       &-block:not(:last-child) { | ||||
|       display: flex; | ||||
|       flex-wrap: wrap; | ||||
|  | ||||
|       > div { | ||||
|         margin-bottom: 20px; | ||||
|         margin-right: 20px; | ||||
|         @include tablet-min { | ||||
|           margin-bottom: 30px; | ||||
|           margin-right: 30px; | ||||
|         } | ||||
|       } | ||||
|       &-title { | ||||
|         margin: 0; | ||||
|         font-weight: 400; | ||||
|         text-transform: uppercase; | ||||
|         font-size: 14px; | ||||
|         color: $green; | ||||
|         @include tablet-min { | ||||
|           font-size: 16px; | ||||
|         & .title { | ||||
|           margin: 0; | ||||
|           font-weight: 400; | ||||
|           text-transform: uppercase; | ||||
|           font-size: 14px; | ||||
|           color: $green; | ||||
|           @include tablet-min { | ||||
|             font-size: 16px; | ||||
|           } | ||||
|         } | ||||
|         & .text { | ||||
|           font-weight: 300; | ||||
|           font-size: 14px; | ||||
|           margin-top: 5px; | ||||
|         } | ||||
|       } | ||||
|       &-text { | ||||
|         font-weight: 300; | ||||
|         font-size: 14px; | ||||
|         margin-top: 5px; | ||||
|       } | ||||
|     } | ||||
|     &__admin { | ||||
|   | ||||
| @@ -1,21 +1,24 @@ | ||||
| <template> | ||||
|   <li class="movies-item" :class="{'shortList': shortList}"> | ||||
|     <a class="movies-item__link" :class="{'no-image': !movie}" @click.prevent="openMoviePopup(movie.id, movie.type)"> | ||||
|   <li class="movie-item" :class="{'shortList': shortList}"> | ||||
|     <figure class="movie-item__poster"> | ||||
|       <img class="movie-item__img is-loaded" | ||||
|            ref="poster-image" | ||||
|            @click="openMoviePopup(movie.id, movie.type)" | ||||
|            :alt="posterAltText" | ||||
|            :data-src="poster" | ||||
|            src="~assets/placeholder.png"> | ||||
|  | ||||
|       <!-- TODO change to picture element --> | ||||
|       <figure class="movies-item__poster"> | ||||
|         <img v-if="movie.poster" class="movies-item__img is-loaded" ref="image" src="~assets/placeholder.png" :alt="`${movie.title} poster image`"> | ||||
|  | ||||
|         <div v-if="movie.download" class="progress"> | ||||
|           <progress :value="movie.download.progress" max="100"></progress> | ||||
|           <span>{{ movie.download.state }}: {{ movie.download.progress }}%</span> | ||||
|         </div> | ||||
|       </figure> | ||||
|       <div class="movies-item__content"> | ||||
|         <p class="movies-item__title">{{ movie.title || movie.name }}</p> | ||||
|         <p class="movies-item__title">{{ movie.year }}</p> | ||||
|       <div v-if="movie.download" class="progress"> | ||||
|         <progress :value="movie.download.progress" max="100"></progress> | ||||
|         <span>{{ movie.download.state }}: {{ movie.download.progress }}%</span> | ||||
|       </div> | ||||
|     </a> | ||||
|     </figure> | ||||
|  | ||||
|     <div class="movie-item__info"> | ||||
|       <p v-if="movie.title || movie.name">{{ movie.title || movie.name }}</p> | ||||
|       <p v-if="movie.year">{{ movie.year }}</p> | ||||
|       <p v-if="movie.type == 'person'">Known for: {{ movie.known_for_department }}</p> | ||||
|     </div> | ||||
|   </li> | ||||
| </template> | ||||
|  | ||||
| @@ -38,6 +41,8 @@ export default { | ||||
|   }, | ||||
|   data(){ | ||||
|     return { | ||||
|       poster: undefined, | ||||
|       observed: false, | ||||
|       posterSizes: [{ | ||||
|         id: 'w500', | ||||
|         minWidth: 500 | ||||
| @@ -54,37 +59,35 @@ export default { | ||||
|     } | ||||
|   }, | ||||
|   computed: { | ||||
|     posterUrl: function() { | ||||
|       if (this.movie.poster == null) | ||||
|         return "~assets/no-image.png" | ||||
|  | ||||
|       const correctWidth = this.posterQualityIdentifierFromPosterWidth | ||||
|  | ||||
|       return `https://image.tmdb.org/t/p/${correctWidth}${this.movie.poster}` | ||||
|     }, | ||||
|     posterQualityIdentifierFromPosterWidth: function() { | ||||
|       const posterWidth = this.$refs.image.clientHeight | ||||
|       if (posterWidth > this.posterSizes[0].minWidth) | ||||
|         return this.posterSizes[0].id | ||||
|  | ||||
|       const widthCandidates = this.posterSizes.filter(size => posterWidth < size.minWidth ? size.id : null) | ||||
|       return widthCandidates[widthCandidates.length - 1].id | ||||
|     posterAltText: function() { | ||||
|       const type = this.movie.type || '' | ||||
|       const title = this.movie.title || this.movie.name | ||||
|       return this.movie.poster ? `Poster for ${type} ${title}` : `Missing image for ${type} ${title}` | ||||
|     } | ||||
|   }, | ||||
|   beforeMount() { | ||||
|     if (this.movie.poster != null) { | ||||
|       this.poster = 'https://image.tmdb.org/t/p/w500' + this.movie.poster | ||||
|     } else { | ||||
|       this.poster = '/dist/no-image.png' | ||||
|     } | ||||
|   }, | ||||
|   mounted() { | ||||
|     if (this.$refs.image == undefined) | ||||
|     const poster = this.$refs['poster-image'] | ||||
|     if (poster == null) | ||||
|       return | ||||
|  | ||||
|     const imageObserver = new IntersectionObserver((entries, imgObserver) => { | ||||
|       entries.forEach((entry) => { | ||||
|         if (entry.isIntersecting) { | ||||
|         if (entry.isIntersecting && this.observed == false) { | ||||
|           const lazyImage = entry.target | ||||
|           lazyImage.src = this.posterUrl | ||||
|           lazyImage.class | ||||
|           lazyImage.src = lazyImage.dataset.src | ||||
|           this.observed = true | ||||
|         } | ||||
|       }) | ||||
|     }); | ||||
|  | ||||
|     imageObserver.observe(this.$refs.image); | ||||
|     imageObserver.observe(poster); | ||||
|   }, | ||||
|   methods: { | ||||
|     openMoviePopup(id, type) { | ||||
| @@ -94,74 +97,103 @@ export default { | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss"> | ||||
| <style lang="scss" scoped> | ||||
| @import "./src/scss/variables"; | ||||
| @import "./src/scss/media-queries"; | ||||
| @import "./src/scss/main"; | ||||
|  | ||||
| .movies-item { | ||||
| .movie-item { | ||||
|   padding: 10px; | ||||
|   width: 50%; | ||||
|   background-color: $background-color; | ||||
|   transition: background-color 0.5s ease; | ||||
|  | ||||
|   @include tablet-min{ | ||||
|   @include tablet-min { | ||||
|     padding: 15px; | ||||
|     width: 33%; | ||||
|   } | ||||
|   @include tablet-landscape-min{ | ||||
|   @include tablet-landscape-min { | ||||
|     padding: 15px; | ||||
|     width: 25%; | ||||
|   } | ||||
|   @include desktop-min{ | ||||
|   @include desktop-min { | ||||
|     padding: 15px; | ||||
|     width: 20%; | ||||
|   } | ||||
|  | ||||
|   @include desktop-lg-min{ | ||||
|   @include desktop-lg-min { | ||||
|     padding: 15px; | ||||
|     width: 12.5%; | ||||
|   } | ||||
|  | ||||
|   &__link{ | ||||
|   &:hover &__info > p { | ||||
|     color: $text-color; | ||||
|   } | ||||
|  | ||||
|   &__poster { | ||||
|     text-decoration: none; | ||||
|     color: $text-color-70; | ||||
|     font-weight: 300; | ||||
|  | ||||
|     > img { | ||||
|       width: 100%; | ||||
|       opacity: 0; | ||||
|       transform: scale(0.97) translateZ(0); | ||||
|       transition: opacity 0.5s ease, transform 0.5s ease; | ||||
|       &.is-loaded{ | ||||
|         opacity: 1; | ||||
|         transform: scale(1); | ||||
|       } | ||||
|  | ||||
|       &:hover { | ||||
|         transform: scale(1.03); | ||||
|         box-shadow: 0 0 10px rgba($dark, 0.1); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   &__content{ | ||||
|  | ||||
|   &__info { | ||||
|     padding-top: 15px; | ||||
|   } | ||||
|   &__poster{ | ||||
|     transition: transform 0.5s ease, box-shadow 0.3s ease; | ||||
|     transform: translateZ(0); | ||||
|   } | ||||
|   &__img{ | ||||
|     width: 100%; | ||||
|     opacity: 0; | ||||
|     transform: scale(0.97) translateZ(0); | ||||
|     transition: opacity 0.5s ease, transform 0.5s ease; | ||||
|     &.is-loaded{ | ||||
|       opacity: 1; | ||||
|       transform: scale(1); | ||||
|     font-weight: 300; | ||||
|  | ||||
|     > p { | ||||
|       color: $text-color-70; | ||||
|       margin: 0; | ||||
|       font-size: 11px; | ||||
|       letter-spacing: 0.5px; | ||||
|       transition: color 0.5s ease; | ||||
|       cursor: pointer; | ||||
|       @include mobile-ls-min{ | ||||
|         font-size: 12px; | ||||
|       } | ||||
|       @include tablet-min{ | ||||
|         font-size: 14px; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   &__link:not(.no-image):hover &__poster{ | ||||
|     transform: scale(1.03); | ||||
|     box-shadow: 0 0 10px rgba($dark, 0.1); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| .no-image { | ||||
|   background-color: var(--text-color); | ||||
|   color: var(--background-color); | ||||
|   width: 100%; | ||||
|   height: 383px; | ||||
|   display: flex; | ||||
|   align-items: center; | ||||
|   justify-content: center; | ||||
|  | ||||
|   span { | ||||
|     font-size: 1.5rem; | ||||
|     width: 70%; | ||||
|     text-align: center; | ||||
|     text-transform: uppercase; | ||||
|   } | ||||
|   &__title{ | ||||
|     margin: 0; | ||||
|     font-size: 11px; | ||||
|     letter-spacing: 0.5px; | ||||
|     transition: color 0.5s ease; | ||||
|     cursor: pointer; | ||||
|     @include mobile-ls-min{ | ||||
|       font-size: 12px; | ||||
|     } | ||||
|     @include tablet-min{ | ||||
|       font-size: 14px; | ||||
|     } | ||||
|   } | ||||
|   &__link:hover &__title{ | ||||
|     color: $text-color; | ||||
|  | ||||
|   &:hover { | ||||
|     transform: scale(1); | ||||
|   } | ||||
| } | ||||
| </style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user