Pure CSS 3 Image Slider - Without JavaScript or Radio Inputs

Pure CSS 3 image slider - without JavaScript or radio inputs

Pure CSS carousel

(...Since you're not allowed to use input radio elements to maintain the active state...)

there's another way to make a sliding gallery in pure CSS(3) using the :target pseudo.

  • :target become those id="foo" elements who are referenced by a clicked anchor with URI Fragment (Hash) href="#foo"

  • In CSS, using :target pseudo you can than reference down-the-tree to other sibling elements using ~ (General sibling selectors), and than you can further access their child elements (slides, buttons etc) as usual.

  • Tip: If you don't like the "feature" of the gallery messing with your URL fragments (Browser Back button triggering a gallery slide instead of navigating the history!), you can always sandbox it - calling your gallery file into an <iframe>.

html, body{height:100%;}
body{font:15px/1 sans-serif; margin:0;}

/*
RESPONSIVE CSS3 SLIDE CAROUSEL GALLERY
http://stackoverflow.com/a/34696029/383904
*/

.CSSgal{
position: relative;
overflow: hidden;
height: 100%; /* Or set a fixed height */
}

/* SLIDER */
.CSSgal .slider{
height: 100%;
white-space: nowrap;
font-size: 0;
transition: 0.8s;
}

/* SLIDES */
.CSSgal .slider > *{
font-size: 1rem;
display: inline-block;
vertical-align: top;
height: 100%;
width: 100%;
background: none 50% no-repeat;
background-size: cover;
}

/* PREV/NEXT, CONTAINERS & ANCHORS */
.CSSgal .prevNext{
position: absolute;
z-index: 1;
top: 50%;
width: 100%;
height: 0;
}
.CSSgal .prevNext > div+div{
visibility: hidden; /* Hide all but first P/N container */
}
.CSSgal .prevNext a{
background: #fff;
position: absolute;
width: 40px;
height: 40px;
line-height: 40px;
text-align: center;
opacity: 0.7;
text-decoration: none;
-webkit-transform: translateY( -50% );
transform: translateY( -50% );
}
.CSSgal .prevNext a:hover{
opacity: 1;
}
.CSSgal .prevNext a+a{
right: 0px;
}

/* NAVIGATION */
.CSSgal .bullets{
position: absolute;
z-index: 2;
bottom: 0;
padding: 10px 0;
width: 100%;
text-align: center;
}
.CSSgal .bullets > a{
display: inline-block;
width: 20px;
height: 20px;
line-height: 20px;
text-decoration: none;
text-align: center;
border-radius: 50%;
background: rgba(255,255,255,1);
}
.CSSgal .bullets > a+a{
background: rgba(255,255,255,0.5); /* Dim all but first */
}
.CSSgal .bullets > a:hover{
background: rgba(0,255,255,0.9);
}

/* ACTIVE NAVIGATION ANCHOR */
.CSSgal >s:target ~ .bullets >* { background: rgba(255,255,255,0.5); }
#s1:target ~ .bullets >*:nth-child(1){ background: rgba(255,255,255, 1); }
#s2:target ~ .bullets >*:nth-child(2){ background: rgba(255,255,255, 1); }
#s3:target ~ .bullets >*:nth-child(3){ background: rgba(255,255,255, 1); }
#s4:target ~ .bullets >*:nth-child(4){ background: rgba(255,255,255, 1); }

/* PREV/NEXT CONTAINERS VISIBILITY */
.CSSgal >s:target ~ .prevNext >* { visibility: hidden; }
#s1:target ~ .prevNext >*:nth-child(1){ visibility: visible; }
#s2:target ~ .prevNext >*:nth-child(2){ visibility: visible; }
#s3:target ~ .prevNext >*:nth-child(3){ visibility: visible; }
#s4:target ~ .prevNext >*:nth-child(4){ visibility: visible; }

/* SLIDER ANIMATION POSITIONS */
#s1:target ~ .slider{ transform: translateX( 0%); -webkit-transform: translateX( 0%); }
#s2:target ~ .slider{ transform: translateX(-100%); -webkit-transform: translateX(-100%); }
#s3:target ~ .slider{ transform: translateX(-200%); -webkit-transform: translateX(-200%); }
#s4:target ~ .slider{ transform: translateX(-300%); -webkit-transform: translateX(-300%); }
<div class="CSSgal">

<!-- Don't wrap targets in parent -->
<s id="s1"></s>
<s id="s2"></s>
<s id="s3"></s>
<s id="s4"></s>

<div class="slider">
<div style="background:#5fc;">Slide 1</div>
<div style="background-image:url('//i.imgur.com/squw4Fw.jpg');"></div>
<div style="background:#fc5;">Slide 3</div>
<div style="background:#f5c;">Slide 4</div>
</div>

<div class="prevNext">
<div><a href="#s4">4</a><a href="#s2">2</a></div>
<div><a href="#s1">1</a><a href="#s3">3</a></div>
<div><a href="#s2">2</a><a href="#s4">4</a></div>
<div><a href="#s3">3</a><a href="#s1">1</a></div>
</div>

<div class="bullets">
<a href="#s1">1</a>
<a href="#s2">2</a>
<a href="#s3">3</a>
<a href="#s4">4</a>
</div>

</div>

CSS: Sliding an image with radio:checked (Pure CSS slider)

Here ya go - consolidated some of your CSS, extended it with a 3rd image, and am using translateX() and opacity to enhance the transition between slides.

img {  position: absolute;  top: 0;  left: 0;  transition: opacity .5s ease-out, transform .5s ease-out;  transform: translateX(-100%);  /* transform: translateX(-100%) rotate(-720deg); */ /* try this, it's nuts */  opacity: 0;}
input[type="radio"] { display: none;}
input:checked + img { transform: translateX(0); /* transform: translateX(0) rotate(0); */ /* try this with the commented line above */ opacity: 1; z-index: 1;}
.controls { position: absolute; top: 0; left: 0; z-index: 2;}
label { background: rgba(0,0,0,0.8); color: #fff; padding: .5em; margin: 0 1em 0 0; display: inline-block; cursor: pointer;}
<div id="wrap">  <input type="radio" id="slide1" name="radio" checked>  <img src="http://kenwheeler.github.io/slick/img/fonz1.png" />  <input type="radio" id="slide2" name="radio">  <img src="http://www.star2.com/wp-content/uploads/2015/06/happy-days-770x470.jpg">    <input type="radio" id="slide3" name="radio">  <img src="https://timedotcom.files.wordpress.com/2016/08/henry-winkler.jpg?quality=85">  <div class="controls">    <label for="slide1">slide1</label>    <label for="slide2">slide2</label>    <label for="slide3">slide3</label>  </div></div>

pure css slider

I hate to say it (because I understand how awesome it feels to make really cool things in pure CSS), but you should use JavaScript.

Bear with me here, and comment if you feel i'm being unreasonable:

You can only have a single element that's matched as :target, because you can only have one hashtag, so at most you can have one slider set to a particular item at a time (the other would return to default). This is the constraint, whether you like it or not.

On the other hand, HTML+CSS+JS is a great example of the Model-View-Controller pattern/model/concept.

  • HTML is the Model as it contains all the data
  • CSS is the View as it contains all the styles
  • JS is the Controller as it defines how the user, data and styles interact with each other.

You're trying to make a slider which involves user interactions. The triggering events (like click) should really be handled by the Controller, not the View.

tl;dr:

You can't do what you're describing in pure CSS.

How can I make an image carousel with only CSS?

That's easy! Just use radio buttons and targeted labels.

Radio buttons have the (necessary) behavior of only allowing one to be selected at any one time—just like an image in our carousel.

Demo

div.wrap2 {  float: left;  height: 500px;  width: 422px;}div.group input {  display: none;  left: -100%;  position: absolute;  top: -100%;}div.group input ~ div.content {  border: solid 1px black;  display: none;  height: 350px;  margin: 0px 60px;  position: relative;  width: 300px;}div.group input:checked ~ div.content {  display: block;}div.group input:checked ~ label.previous,div.group input:checked ~ label.next {  display: block;}div.group label {  background-color: #69c;  border: solid 1px black;  display: none;  height: 50px;  width: 50px;}img {  left: 0;  margin: 0 auto;  position: absolute;  right: 0;}p {  text-align: center;}label {  font-size: 4em;  margin: 125px 0 0 0;}label.previous {  float: left;  padding: 0 0 30px 5px;}label.next {  float: right;  padding: 0 5px 25px 0;  text-align: right;}
<div class="wrap">  <div class="wrap2">    <div class="group">      <input type="radio" name="test" id="0" value="0">      <label for="4" class="previous"><</label>      <label for="1" class="next">></label>      <div class="content">        <p>panel #0</p>        <img src="http://i.stack.imgur.com/R5yzx.jpg" width="200" height="286">      </div>    </div>    <div class="group">      <input type="radio" name="test" id="1" value="1">      <label for="0" class="previous"><</label>      <label for="2" class="next">></label>      <div class="content">        <p>panel #1</p>        <img src="http://i.stack.imgur.com/k0Hsd.jpg" width="200" height="139">      </div>    </div>    <div class="group">      <input type="radio" name="test" id="2" value="2">      <label for="1" class="previous"><</label>      <label for="3" class="next">></label>      <div class="content">        <p>panel #2</p>        <img src="http://i.stack.imgur.com/Hhl9H.jpg" width="140" height="200">      </div>    </div>    <div class="group">      <input type="radio" name="test" id="3" value="3" checked="">      <label for="2" class="previous"><</label>      <label for="4" class="next">></label>      <div class="content">        <p>panel #3</p>        <img src="http://i.stack.imgur.com/r1AyN.jpg" width="200" height="287">      </div>    </div>    <div class="group">      <input type="radio" name="test" id="4" value="4">      <label for="3" class="previous"><</label>      <label for="0" class="next">></label>      <div class="content">        <p>panel #4</p>        <img src="http://i.stack.imgur.com/EHHsa.jpg" width="96" height="139">      </div>    </div>  </div></div>

Pure css tabs without radio button

Alright, using the :target pseudo-class we can achieve this.

EDIT: I added a wrapper div so you can use position absolute on the panels. This allows you to have the first panel open and switch between them.

.wrapper {  position: relative;}.tab-container {   display: none;  position: absolute;  top: 0;  left: 0;  background: red;}
.tab-container:first-child { display: block }
:target { display: block }

/* just for demo */
ul { list-style: none; margin: 0; padding: 0;}
li { display: inline-block; margin-right: 1rem;}
<ul>  <li><a href="#tab-1-container">Tab 1</a></li>  <li><a href="#tab-2-container">Tab 2</a></li>  <li><a href="#tab-3-container">Tab 3</a></li></ul>
<div class="wrapper"> <div id="tab-1-container" class="tab-container"> Tab 1 content </div>
<div id="tab-2-container" class="tab-container"> Tab 2 content </div>
<div id="tab-3-container" class="tab-container"> Tab 3 content </div></div>

Moving a slideshow using CSS/HTML

Since you haven't described which type of slideshow you need, I have created slideshow which can either run automatically or can be controlled by the user. After user click or site load, it start automatic slide show in 10s. Automatic slideshow change slides in every 3s. Check out this snippet:

var slideIndex = 0;
var timer1, timer;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("dot");

function showSlides() {//called by automatic slideshow
clearTimeout(timer1);//clear previously set timer

//clear styles
for (var i = 0; i < slides.length; i++)
slides[i].style.display = "none";
for (var i = 0; i < dots.length; i++)
dots[i].className = dots[i].className.replace(" active", "");

//reset slideIndex
if (++slideIndex == slides.length)
slideIndex = 0;

//reset styles
slides[slideIndex].style.display = "block";
dots[slideIndex].className += " active";

//reset timer
timer1 = setTimeout(showSlides, 3000);
}

function showSlide(n) {//called when user manually choose particular slide
//clear previously set timers
clearTimeout(timer1);
clearTimeout(timer);

//clear styles
for (var i = 0; i < slides.length; i++)
slides[i].style.display = "none";
for (var i = 0; i < dots.length; i++)
dots[i].className = dots[i].className.replace(" active", "");

//reset slideIndex
if (n == slides.length)
slideIndex = 0;
if (n < 0)
slideIndex = slides.length;

//reset styles
slides[slideIndex].style.display = "block";
dots[slideIndex].className += " active";

//reset timer for automatic slideshow
timer = setTimeout(showSlides, 10000);
}
/* make width, height, min/max properties includes content, padding and border */
* {box-sizing:border-box}

/* Slideshow container */
.slideshow-container {
width: 50vw;
height: 50vh;
position: relative;
margin: auto;
clear:both;
background-color: black;
}

/* Hide the images by default */
.mySlides {
display: none;
}

/* make images fit to slide width */
.mySlides img {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
text-align: center;
height: 50vh; object-fit: fill;
}

/* Next & previous buttons */
.prev, .next {
cursor: pointer;
position: absolute;
top: 50%;
margin: 0;
width: auto;
padding: 16px;
color: white;
font-weight: bold;
font-size: xx-large;
transition: 0.6s;
user-select: none;
-ms-transform: translateY(-50%);
transform: translateY(-50%);

}

/* Position the "next button" to the right */
.next {
right: 0;
}

/* On hover, add a black background color with a little bit see-through */
.prev:hover, .next:hover {
background-color: black;
opacity: 0.7;
}

/* Caption text */
.text {
color: #f2f2f2;
font-size: 4em;
padding-bottom: : 12px;
position: absolute;
bottom: 8px;
width: 100%;
text-align: center;
}

/* Number text (1/3 etc) */
.numbertext {
color: #f2f2f2;
font-size: 1.5em;
padding: 8px 12px;
position: absolute;
top: 0;
z-index: 1;
}

/* Dots container */
.dots-container {
text-align: center;
}

/* The dots/bullets/indicators */
.dot {
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 2px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
}

.active, .dot:hover {
background-color: #717171;
}

/* Fading animation */
.fade {
-webkit-animation-name: fade;
-webkit-animation-duration: 1.5s;
animation-name: fade;
animation-duration: 1.5s;
}

@-webkit-keyframes fade {
from {opacity: .4}
to {opacity: 1}
}

@keyframes fade {
from {opacity: .4}
to {opacity: 1}
}

/* Small devices specific alterations */
@media only screen and (max-width: 600px) {
/* Slideshow container */
.slideshow-container {
width: 96vw;
}

.text {
font-size: 1.5em;
}

.numbertext {
font-size: 1em;
}

/* Next & previous buttons */
.prev, .next {
padding: 4px;
font-weight: bold;
font-size: large;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Apple</title>
</head>
<!-- start slideshow on page load. -->
<body onload="showSlide(1);">
<div class="title">
<h1>Photoreal Scenery</h1>
</div>

<!-- Slideshow container -->
<div class="slideshow-container">

<!-- Full-width images with number and caption text -->
<div class="mySlides fade" >
<div class="numbertext">1 / 4</div>
<img src="red.png">
<div class="text">Caption Text</div>
</div>

<div class="mySlides fade">
<div class="numbertext">2 / 4</div>
<img src="blue.png">
<div class="text">Caption Two</div>
</div>

<div class="mySlides fade">
<div class="numbertext">3 / 4</div>
<img src="green.png">
<div class="text">Caption Three</div>
</div>

<div class="mySlides fade">
<div class="numbertext">4 / 4</div>
<img src="j.jpg">
<div class="text">Caption Three</div>
</div>

<!-- Next and previous buttons -->
<a class="prev" onclick="showSlide(--slideIndex);">❮</a>
<a class="next" onclick="showSlide(++slideIndex);">❯</a>
</div>
<br>

<!-- The dots/circles -->
<div class="dots-container">
<span class="dot" onclick="showSlide(slideIndex = 0)"></span>
<span class="dot" onclick="showSlide(slideIndex = 1)"></span>
<span class="dot" onclick="showSlide(slideIndex = 2)"></span>
<span class="dot" onclick="showSlide(slideIndex = 3)"></span>
</div>
</body>
</html>


Related Topics



Leave a reply



Submit