4

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
J86
  • 14,345
  • 47
  • 130
  • 228
  • 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. – Cyval Jan 09 '16 at 02: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? – Roko C. Buljan Jan 09 '16 at 02: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? – Drakes Jan 09 '16 at 13:02
  • 1
    @Cyval that just isn't true anymore. – J86 Jan 09 '16 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. – J86 Jan 09 '16 at 13:55

1 Answers1

28

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>
Community
  • 1
  • 1
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • @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... – Roko C. Buljan Jan 09 '16 at 17:16
  • 1
    Is there a way to make this works with arrows rather than active bullets? Two arrows for left and right? – J86 Jan 10 '16 at 01:23
  • 1
    @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. – Roko C. Buljan Jan 10 '16 at 03:09
  • 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. – Shardul Nov 26 '20 at 22:52
  • @Shardul well, not if you create a tool (with JavaScript or other) to help in the making. But now, it's not dynamic. If you need something dynamic than you don't need a static HTML/CSS-only solution at all. You can use a JS slider. – Roko C. Buljan Nov 27 '20 at 01:33
  • @RokoC.Buljan how can I use only three slides and have it always go forward, so after 3 the first one slides in from the righ to left? – Martina Schuberth Sep 02 '23 at 08:06
  • @MartinaSchuberth I don't think CSS is the right tool to create an ***infinite slideshow***. You might want to take a look at i.e: [this infinite slideshow](https://stackoverflow.com/a/72992704/383904) that uses JavaScript - if that is what you were looking for – Roko C. Buljan Sep 02 '23 at 10:47
  • @RokoC.Buljan thanks, but I don't need autoplay, and no bullets. How could I remove both? – Martina Schuberth Sep 02 '23 at 15:47
  • @MartinaSchuberth Here's an example with the removed JS and CSS related parts: https://jsfiddle.net/1z4wd7mc/ – Roko C. Buljan Sep 02 '23 at 16:13