5

Is there a way one can create an image slider using just CSS 3 and HTML, but without using any of the HTML input (radio) elements and no JavaScript?

I had massive search sessions and found stuff that was close and worked well, but it was using the HTML radio input.

5
  • You should always remember that CSS layer in web development has nothing to do with behavior / structure and content. CSS is the style layer, so it is about style. You cannot slide through images with merely styles. Commented Jan 9, 2016 at 2:24
  • What lead you to the info that for a gallery slider you need input elements?? Have you done any research at all? Any code to share? What and why it did not worked for you? Commented Jan 9, 2016 at 2:28
  • You'd have to use link fragments (e.g. /#image1) to navigate between images on the same page, and contain them all in some fixed container div. This will make the page jump to the top of the fixed div each time though. This is what we did 15 years ago! There are far more elegant solutions today. Why such strict requirements? Commented Jan 9, 2016 at 13:02
  • 1
    @Cyval that just isn't true anymore. Commented Jan 9, 2016 at 13:45
  • 1
    @RokoC.Buljan what lead me to think that an input had to be used was that everything I came across made use of input elements. It is intended for eBay, and on there you can't use JavaScript nor Input elements in your listing. Commented Jan 9, 2016 at 13:55

1 Answer 1

31

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>

Sign up to request clarification or add additional context in comments.

23 Comments

@Ciwan you're welcome. Note that the above will not work in older browsers 1. cause the use of CSS3 transition, 2. cause of the CSS ~ selector. Also don't forget to add all the necessary -vendor- prefixes like for -webkit-transition etc...
Is there a way to make this works with arrows rather than active bullets? Two arrows for left and right?
@Ciwan that complicates the HTML (and CSS) a lot but it's doable. Simply, for every slide you need a pair of PREV/NEXT buttons (anchors) with the proper URI Fragment (Hash) href="#sN" which will point to the prev/next slide accordingly.
How to add more than 4 slides? 👉 Figured it out. You have to change the CSS too. Although good, this is not a very scalable solution. Too many changes needed to add extra slides.
This is the best example I've found for a pure CSS slideshow. One change I made in my implementation was to change the <s> elements to <dfn> elements (in order to satisfy strict HTML5 validation).
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.