Inspired by the breakdown of Netflix's show carousel.
Base forked from Eli White's Pen xGpxXv, with the CSS-selector kung foo done in Matt Taylor's pen
<div class="contain"> | |
<h1>Pure CSS Netflix Video Carousel</h1> | |
<p> | |
Inspired by <a href="https://twitter.com/Eli_White">Eli White's</a> article <a href="http://eng.wealthfront.com/2015/06/implementing-netflix-redesign.html">Performant CSS Animations: Netflix Case Study</a>, his <a href="https://codepen.io/TheSavior/pen/LVeYBp">example pen</a>, and <a href="http://matthewjamestaylor.com/">Matt Taylor's</a> <a href="https://codepen.io/mattjamestaylor/pen/dodYPr">CSS-only version.</a> | |
</p> | |
<div class="row"> | |
<div class="row__inner"> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-1.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-2.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-3.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-4.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-5.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-6.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-7.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-8.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-9.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-10.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-11.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-12.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-13.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-14.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-15.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-16.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-17.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-18.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
<div class="tile"> | |
<div class="tile__media"> | |
<img class="tile__img" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/70390/show-19.jpg" alt="" /> | |
</div> | |
<div class="tile__details"> | |
<div class="tile__title"> | |
Top Gear | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
$duration = 450ms | |
$tileWidth = 250px | |
$tileHeight = ($tileWidth / (16/9)) | |
$iconSize = 50px | |
$growFactor = 1.5 // 1.5 times the original size | |
$moveLeft = -($tileWidth * ($growFactor - 1) / 2) | |
$moveRight = $tileWidth * ($growFactor - 1) | |
body, html | |
padding: 0 10px | |
margin: 0 | |
background: #0E0F11 | |
color: #ecf0f1 | |
font-family: 'Open Sans', sans-serif | |
min-height: 100vh | |
display: flex | |
flex-direction: row | |
align-items: center | |
width: 100% | |
* { box-sizing: border-box } | |
h1, p | |
text-align: center | |
p | |
width: 100% | |
max-width: 500px | |
margin: auto | |
a:link | |
a:hover | |
a:active | |
a:visited | |
transition: color 150ms | |
color: #95a5a6 | |
text-decoration: none | |
a:hover | |
color: #7f8c8d | |
text-decoration: underline | |
.contain | |
width: 100% | |
.row | |
overflow: scroll | |
width: 100% | |
.row__inner | |
transition: $duration transform | |
font-size: 0 | |
white-space: nowrap | |
margin: ($tileHeight / 2) 0 | |
padding-bottom: 10px // Account for OS X scroll bar | |
.tile | |
position: relative | |
display: inline-block | |
width: $tileWidth | |
height: $tileHeight | |
margin-right: 10px | |
font-size: 20px | |
cursor: pointer | |
transition: $duration all | |
transform-origin: center left | |
.tile__img | |
width: $tileWidth | |
height: $tileHeight | |
object-fit: cover | |
.tile__details | |
position: absolute | |
bottom: 0 | |
left: 0 | |
right: 0 | |
top: 0 | |
font-size: 10px | |
opacity: 0 | |
background: linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0) 100%) | |
transition: $duration opacity | |
&:after | |
&:before | |
content: '' | |
position absolute | |
top: 50% | |
left: 50% | |
display: black | |
&:after | |
margin-top: (-($iconSize / 2)) | |
margin-left: (-($iconSize / 2)) | |
width: $iconSize | |
height: $iconSize | |
border: 3px solid #ecf0f1 | |
line-height: $iconSize | |
text-align: center | |
border-radius: 100% | |
background: rgba(0,0,0,0.5) | |
z-index: 1 | |
&:before | |
content: '▶' | |
left: 0 | |
width: 100% | |
font-size: 30px | |
margin-left: 7px | |
margin-top: -18px | |
text-align: center | |
z-index: 2 | |
.tile:hover & | |
opacity: 1 | |
.tile__title | |
position absolute | |
bottom: 0 | |
padding: 10px | |
// * | |
// * Hover effects | |
// * | |
// We assume when you hover .row, you're also hovering a .tile | |
// First, move the whole row towards the left | |
.row__inner:hover | |
transform: translate3d($moveLeft, 0, 0) | |
.row__inner:hover .tile | |
// Fade out every tile | |
opacity: .3 | |
// And then grow the current tile and make it opaque again | |
&:hover | |
transform: scale($growFactor) | |
opacity: 1 | |
// And finally move all tiles right of the current tile to the right, | |
// so its flush against the hovered tile | |
.tile:hover ~ .tile | |
transform: translate3d($moveRight, 0, 0) | |