I\'m looking to make an image carousel, where a user can toggle between images, by clicking on arrows. For example:
Inspired by royhowie I ended up with a much simpler solution if it comes to HTML syntax. Also, with nice animation and fully customizable!
The main idea was to create the arrows not by placing them in HTML one by one, but by creating and then carefully positioning pseudoelements.
* {
-ms-box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.CSS_slideshow {
display: block;
width: 600px;
height: 425px;
overflow: hidden;
margin: 0 auto;
-ms-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
user-select: none;
text-space-collapse: trim-inner;
}
.CSS_slideshow[data-show-indicators="true"][data-indicators-position="in"] {
-webkit-margin-after: -25px; /* Removes the space under the slideshow. Webkit only as only Webkit-based browsers will support the dots in the wrapper */
}
/* Defines animation timing function */
.CSS_slideshow[data-animation-style] {
-moz-transition-timing-function: ease-in-out;
-webkit-transition-timing-function: ease-in-out;
transition-timing-function: ease-in-out;
}
/* Inherit all animation properties from parent element */
.CSS_slideshow[data-animation-style] *,
.CSS_slideshow[data-show-buttons="true"][data-animation-style] label:before,
.CSS_slideshow[data-show-buttons="true"][data-animation-style] label:after {
-moz-transition-duration: inherit;
-webkit-transition-duration: inherit;
transition-duration: inherit;
-moz-transition-timing-function: inherit;
-webkit-transition-timing-function: inherit;
transition-timing-function: inherit;
}
/* WRAPPER */
.CSS_slideshow_wrapper {
display: block;
width: 600px;
height: 400px;
position: relative;
/* Styling */
text-align: center;
}
/* Indicators */
.CSS_slideshow[data-show-indicators="true"] input {
width: 10px;
height: 10px;
outline: none;
position: relative;
top: calc(100% + 7px);
-ms-transform: scale(1); /* Fallback for Internet Explorer: supports radio button resizing, does not support :after. Not necessary, put for readibility. */
-moz-transform: scale(0.6); /* Fallback for Firefox: does not radio button resizing, does not support :after */
-webkit-appearance: none; /* hide radio buttons for Webkit: supports :after */
}
.CSS_slideshow[data-show-indicators="true"] input:checked {
-ms-transform: scale(1.25); /* Fallback for Internet Explorer: supports radio button resizing, does not support :after */
-moz-transform: scale(0.9); /* Fallback for Firefox: it does not do radio button resizing, does not support :after */
}
/* Webkit-only goodness - for now */
.CSS_slideshow[data-show-indicators="true"] input:after {
content: '';
display: block;
position: absolute;
left: 0;
width: 8px;
height: 8px;
border: 1px solid;
border-radius: 100%;
cursor: pointer;
z-index: 4;
-moz-transition-property: transform, background;
-webkit-transition-property: transform, background;
transition-property: transform, background;
}
.CSS_slideshow[data-show-indicators="true"][data-indicators-position="under"] input:after {
top: -2px;
background: rgba(0, 0, 0, 0);
border-color: rgb(0, 0, 0);
}
.CSS_slideshow[data-show-indicators="true"][data-indicators-position="in"] input:after {
top: -35px;
box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.25), 0 0 2px rgba(0, 0, 0, 0.25);
background: rgba(235, 235, 235, 0);
border-color: rgb(235, 235, 235);
}
.CSS_slideshow[data-show-indicators="true"] input:checked:after {
-webkit-transform: scale(1.25);
}
.CSS_slideshow[data-show-indicators="true"][data-indicators-position="under"] input:checked:after {
background: rgb(0, 0, 0)
}
.CSS_slideshow[data-show-indicators="true"][data-indicators-position="in"] input:checked:after {
box-shadow: 0 0 2px rgba(0, 0, 0, 0.25);
background: rgb(235, 235, 235);
}
.CSS_slideshow:not([data-show-indicators="true"]) input {
display: none;
}
/* SLIDES */
.CSS_slideshow label {
display: inline-block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
}
.CSS_slideshow[data-animation-style="slide"] label {
-moz-transition-property: left;
-webkit-transition-property: left;
transition-property: left;
}
.CSS_slideshow label img {
width: 100%;
height: 100%;
}
/* Puts all the slides on the left... */
.CSS_slideshow label {
left: -100%;
}
/* ...except the ones coming after input:checked - those are put on the right... */
.CSS_slideshow input:checked ~ label {
left: 100%;
}
/* ...except the one coming directly after input:checked - this is our current slide and it's in the middle */
.CSS_slideshow input:checked + label {
left: 0;
}
/* PREV/NEXT ARROWS */
.CSS_slideshow[data-show-buttons="true"] label:before,
.CSS_slideshow[data-show-buttons="true"] label:after {
display: block;
position: absolute;
width: 60px;
height: 60px;
top: calc((100% - 60px) / 2);
/* Styling */
background: rgb(235, 235, 235);
font-size: 35px;
font-weight: 800;
font-family: Consolas;
line-height: 56px;
color: black;
z-index: 1;
cursor: pointer;
}
.CSS_slideshow[data-show-buttons="true"][data-animation-style="slide"] label:before,
.CSS_slideshow[data-show-buttons="true"][data-animation-style="slide"] label:after {
-moz-transition-property: left, right;
-webkit-transition-property: left, right;
transition-property: left, right;
}
.CSS_slideshow[data-show-buttons="true"] label:hover:before,
.CSS_slideshow[data-show-buttons="true"] label:hover:after {
/* Styling */
background: rgb(245, 245, 245);
}
/* Slides on the left */
/* Since the slides are on the left, we need to move the buttons 100% to the right */
.CSS_slideshow[data-show-buttons="true"] label:before {
right: -100%;
opacity: 0;
/* Styling */
content: '>'; /* next */
}
.CSS_slideshow[data-show-buttons="true"] label:after {
left: 100%;
opacity: 1;
/* Styling */
content: '<'; /* previous */
}
/* Slides on the right */
/* Since the slides are on the right, we need to move the buttons 100% to the left */
.CSS_slideshow[data-show-buttons="true"] input:checked ~ label:before {
right: 100%;
opacity: 1;
}
.CSS_slideshow[data-show-buttons="true"] input:checked ~ label:after {
left: -100%;
opacity: 0;
cursor: default;
}
/* Active slide */
/* And for the active slide - just usual positioning */
.CSS_slideshow[data-show-buttons="true"] input:checked + label:before {
right: 0;
opacity: 0;
cursor: default;
}
.CSS_slideshow[data-show-buttons="true"] input:checked + label:after {
left: 0;
}
/* Buttons positioning */
.CSS_slideshow[data-show-buttons="true"] label:after {
z-index: 3; /* move "previous" buttons forward... */
}
.CSS_slideshow[data-show-buttons="true"] input:checked ~ label:after {
z-index: 1; /* ...except the one for an active slide - this should be hidden - causes the "previous" arrow from the previous slide to be on top */
}
.CSS_slideshow[data-show-buttons="true"] input:checked + label + input + label:before {
z-index: 3; /* move "next" button one slide ahead forward - causes the "next" arrow from the next slide to be on top */
}
/* WRAP ARROWS */
/* We'll reuse "previous" arrow from the first slide and "next" arrow from the last to make "wrap" buttons, based on roughly the same principles */
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] label:first-of-type:before,
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] label:last-of-type:after {
z-index: 2 !important;
opacity: 1 !important;
cursor: pointer !important;
/* Styling */
letter-spacing: -9px;
text-align: left;
padding-left: 14px;
width: 46px;
}
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] label:first-of-type:before {
content: '<<'; /* jump to first */
right: 0 !important;
}
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] input:not(:checked) + label:first-of-type:before {
right: -100% !important;
}
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] label:last-of-type:after {
content: '>>'; /* jump to last */
left: 0 !important;
}
.CSS_slideshow[data-show-buttons="true"][data-show-wrap-buttons="true"] input:not(:checked) + label:last-of-type:after {
left: -100% !important;
}
/* Non-CSS slideshow CSS */
body {
font-family: Segoe UI, Tahoma, sans-serif;
font-size: 14px;
}
#license {
margin-top: 3em;
text-align: center;
font-size: 10px;
}
#license * {
font-size: 10px;
}

Pure CSS slideshow by Wojciech Maj is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
You can read more about customizations and some technical limitations on my fiddle.