Fullscreen Background Image Slideshow with CSS3

Happy new year, everybody! Today we will create a CSS-only fullscreen background image slideshow. We’ll create different image transitions and also make a title appear using CSS animations.

CSS3FullscreenSlideshow

Happy new year, everybody! Today we will create a CSS-only fullscreen background image slideshow. We’ll create different image transitions and also make a title appear using CSS animations.

The images are by Mark Sebastian and they are licensed under the Creative Commons Attribution-ShareAlike 2.0 Generic License.

Note that this will only work in browsers supporting CSS animations.

This tutorial is a part of our latest CSS3 experiments; you can find more of those here:

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

The Markup

We’ll use an unordered list for the slideshow and we’ll add a span for each image and a division with a heading:

<ul class="cb-slideshow">
	<li>
		<span>Image 01</span>
		<div>
			<h3>re·lax·a·tion</h3>
		</div>
	</li>
	<li><!--...--></li>
	<li><!--...--></li>
</ul>

The spans are going to be the elements that will have the background images of the slideshow.

The CSS

Let’s style the unordered list first. It will be fixed and we will stretch it over the viewport. We’ll also use a :after pseudo-element in order to place a pattern on top of the image:

.cb-slideshow,
.cb-slideshow:after { 
    position: fixed;
    width: 100%;
    height: 100%;
    top: 0px;
    left: 0px;
    z-index: 0; 
}
.cb-slideshow:after { 
    content: '';
    background: transparent url(../images/pattern.png) repeat top left; 
}

We’ll use a repeated dot pattern but you could as well use, for example, a css gradient with some transparency.

The span that will contain a slideshow image will be positioned absolutely and have a width and height of 100%. Since we have some text inside, we’ll make the color transparent because we don’t want to see it. The background-size property value “cover” will make sure that the background image covers all the area of the element and hence it is the size of the screen, it will cover all the visible viewport. The opacity is set to 0. We’ll then change that in our animation:

.cb-slideshow li span { 
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
    color: transparent;
    background-size: cover;
    background-position: 50% 50%;
    background-repeat: none;
    opacity: 0;
    z-index: 0;
    animation: imageAnimation 36s linear infinite 0s; 
}

The animation for each span will last 36 seconds and run an inifinite number of times. But let’s look at the details in a while, first, we will style the division with the headline:

.cb-slideshow li div { 
    z-index: 1000;
    position: absolute;
    bottom: 30px;
    left: 0px;
    width: 100%;
    text-align: center;
    opacity: 0;
    color: #fff;
    animation: titleAnimation 36s linear infinite 0s; 
}
.cb-slideshow li div h3 { 
    font-family: 'BebasNeueRegular', 'Arial Narrow', Arial, sans-serif;
    font-size: 240px;
    padding: 0;
    line-height: 200px; 
}

The animation for the title division will also take 36 seconds.

Now, we will define the background images for all the spans and the animation delay, so that each following slideshow image and title appear after 6 second of the previous one:

.cb-slideshow li:nth-child(1) span { 
    background-image: url(../images/1.jpg) 
}
.cb-slideshow li:nth-child(2) span { 
    background-image: url(../images/2.jpg);
    animation-delay: 6s; 
}
.cb-slideshow li:nth-child(3) span { 
    background-image: url(../images/3.jpg);
    animation-delay: 12s; 
}
.cb-slideshow li:nth-child(4) span { 
    background-image: url(../images/4.jpg);
    animation-delay: 18s; 
}
.cb-slideshow li:nth-child(5) span { 
    background-image: url(../images/5.jpg);
    animation-delay: 24s; 
}
.cb-slideshow li:nth-child(6) span { 
    background-image: url(../images/6.jpg);
    animation-delay: 30s; 
}

.cb-slideshow li:nth-child(2) div { 
    animation-delay: 6s; 
}
.cb-slideshow li:nth-child(3) div { 
    animation-delay: 12s; 
}
.cb-slideshow li:nth-child(4) div { 
    animation-delay: 18s; 
}
.cb-slideshow li:nth-child(5) div { 
    animation-delay: 24s; 
}
.cb-slideshow li:nth-child(6) div { 
    animation-delay: 30s; 
}

Now, let’s have a look at the slideshow animation. Each span will have an animation time of 36 seconds. In those 36 seconds we will change the opacity from 0 to 1 when the animation reaches 8%. And then this opacity gets kept until 17% are reached. When reaching 25% the opacity should already be 0 again and stay like that until the end.

Now, why those values? We want each image to be visible for 6 seconds and we know that at the end of a cycle, we want the first image to show again. We have 6 images, so we will need 36 seconds for a whole cycle to finish. Now, we need to “time” the opacity values accordingly. Knowing that our second image will start animating at 6 seconds, we need to know at what percentile of the animation this will require the first image to fade out. Dividing 6 by 36 gives us 0.166… which would be 16% for our keyframe step. Now, because we don’t want our image to just fade all the time, we’ll define an inbetween step, which we’ll set at half of what we calculated, i.e. 8%. That’s the point that we want to show the image completely and we only want to start fading it out at 17%, making it disappear completely at 25%.

@keyframes imageAnimation { 
    0% { opacity: 0; animation-timing-function: ease-in; }
    8% { opacity: 1; animation-timing-function: ease-out; }
    17% { opacity: 1 }
    25% { opacity: 0 }
    100% { opacity: 0 }
}

We have the same reasoning for the title, just that we want it to disappear a bit quicker, hence the opacity 0 at 19%:

@keyframes titleAnimation { 
    0% { opacity: 0 }
    8% { opacity: 1 }
    17% { opacity: 1 }
    19% { opacity: 0 }
    100% { opacity: 0 }
}

For browsers that don’t support animations, we’ll simply show the last slideshow image by setting the opacity of the span to 1:

.no-cssanimations .cb-slideshow li span{
	opacity: 1;
}

The no-cssanimations class is added by Modernizr.

Let’s as well take care of the title’s font size when the viewport is smaller. We’ll use media queries in order to set the font size smaller at specific widths:

@media screen and (max-width: 1140px) { 
    .cb-slideshow li div h3 { font-size: 140px }
}
@media screen and (max-width: 600px) { 
    .cb-slideshow li div h3 { font-size: 80px }
}

And that’s all for the simple version of the slideshow! Now, let’s see how we can spice up the transitions a bit.

Alternative animation example

Now, we can play a bit with the animations for showing the images and their titles.

The following animation will make the image scale up a bit and rotate it slightly:

@keyframes imageAnimation { 
	0% {
	    opacity: 0;
	    animation-timing-function: ease-in;
	}
	8% {
	    opacity: 1;
	    transform: scale(1.05);
	    animation-timing-function: ease-out;
	}
	17% {
	    opacity: 1;
	    transform: scale(1.1) rotate(3deg);
	}
	25% {
	    opacity: 0;
	    transform: scale(1.1) rotate(3deg);
	}
	100% { opacity: 0 }
}

The title will slide in from the right (we’ll have to change the text-align for the title division to “right”), and disappear by sliding to the left and fading out:

@keyframes titleAnimation { 
	0% {
	    opacity: 0;
	    transform: translateX(200px);
	}
	8% {
	    opacity: 1;
	    transform: translateX(0px);
	}
	17% {
	    opacity: 1;
	    transform: translateX(0px);
	}
	19% {
	    opacity: 0;
	    transform: translateX(-400px);
	}
	25% { opacity: 0 }
	100% { opacity: 0 }
}

There are many possibilities for the image and title transitions, just experiment!

Demos

Here you can find some demos with alternative animations:

  1. Demo 1: Simple Fade in, fade out
  2. Demo 2: Slight rotation, title slides from the right
  3. Demo 3: Image moves up, title moves down
  4. Demo 4: Image scales, title moves up, scales and fades out

Currently, the animations are smoothest in Webkit broswers like Chrome and especially Safari.

I hope you enjoyed this tutorial and find it useful and inspiring!

Manoela Ilic

Manoela is the main tinkerer at Codrops. With a background in coding and passion for all things design, she creates web experiments and keeps frontend professionals informed about the latest trends.

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 150

Comments are closed.
  1. Hello,

    I really like your tutorial.
    There only seems to be a problem when zooming in or making multitouch gestures on the iPad.
    I don’t know how to solve this.
    Even when disabling the zoom option by setting meta tag:

    It still crashes when the multi touch gestures are done..

    Can anyone help me?

    Regards!

    • That’s why Internet explorer doesn’t support any kind of css3 transitions or effects, for example: animation-timing-function, animation, animation-delay and more, It’s really simple, If you want to see or use CSS3 effects like transitions, transform and more, then you SHOULD Dump Internet Explorer.

      Btw Mary! this tutorial it’s really awesome and usefull! I was wondering how to do something like that just with CSS3! thanks for sharing!

  2. Hi great work!! I’m wondering how I can combine this with lets say the slideshow with parallax effect on top. Not with regards to multiple java-script but where in the div structure, believe me Ive tried. Thank you.

  3. Hello,
    Thanks for this tutorial. GREAT WORK !
    I want to use it with a video background
    Do you know how to do it ?

  4. this is great, but, is there a way to make the images show in randome order?

  5. I get an odd effect when I attempt to cut down the slides to 3, the first slide fires fine, but the second one just goes to black, then 6 seconds later it displays the actual second image, does the same thing for the 3rd(goes to black) then displays the actual 3rd slide.

    Any ideas on how to fix this?

  6. Love it other then it lags the crap out of my site. Can you make a pause please thanks.

  7. Just managed to implement it in this background slideshow in Drupal… to save others some other some time here are the steps:

    – paste the markup into page.tpl.php of your template, right at the top just under the first tag
    – paste the css into styles.css of your template, at the bottom
    – in the css change all the z-index values to -1
    -copy the images folder into your template’s root folder
    – copy the fonts folder into the template’s css folder

    that should be it…

  8. The demo seems to break in Chrome (19.0.1084.46) if you switch to a different tab and return. In the page I’m building based on this method, removing “-webkit-backface-visibility: hidden;” from the CSS seemed to resolve the issue.

  9. OK: so “-webkit-backface-visibility: hidden” tells webkit to treat the images as a 3D object which triggers it to perform the animation using webGL, which is _mostly_ a good thing, because it makes the animation WAAAAY smoother in Safari.

    The downside of that line of CSS is that up to somewhere around Chrome 21.X canary (unreleased as of yet) triggering webGL causes the CSS Animation’s to all reset if you switch tabs and return to the page. This not only resets the gallery to play from the beginning, it removes the animation-delays causing all the animations to play at the same time resulting in a completely broken gallery.

    To fix this on my website, I moved the “-webkit-backface-visibility: hidden” into a selector .use-web-gl { }, then on my page, I add this class to all browsers except versions of Chrome before ‘canary’ using jQuery as follows:


    if ( $.browser.webkit && !!window.chrome && $.browser.version < 537.1 ) {
    // do not use web GL
    } else {
    $(".cb-slideshow li").addClass('use-web-gl');
    }

    By doing this, you get the best of both – webGL in Safari = nice smooth transitions. No web-GL for Chrome < 21.X = no messed up timings when returning from another tab.

    🙂

    • so.. i´m trying to fix mine too.. but i dont understend what u have done with the “-webkit-backface-visibility: hidden”, did u put it on the css class: .use-web-gl { }?

      and this if/else… u put in your page scripts?

      can u show me your exemple of code?
      sry about the nb questions… trying to learn in here T_T…

    • Could you please show an example? I’m having that issue as well. Thanks!

    • For anyone who is looking for a snippet of this example:
      /* CSS */
      .use-web-gl {
      -webkit-backface-visibility: hidden;
      }
      /* HTML */
      [page content]

      $(document).ready(function() {
      if($.browser.webkit && !!window.chrome && $.browser.version < 537.1) {
      // do not use web GL
      } else {
      /*
      * Forces fullscreen CSS3 slideshow to use WebGL if browser is able to,
      * because it creates smoother transitions
      */
      $(".slideshow li").addClass('use-web-gl');
      }
      });

      [footer/end body tag area]

      Ideally all you want to do is initialize that chunk of code so that it checks the browser and injects the CSS using jQuery when the browser isn’t that particular Chrome Canary version. Correct me if I’m wrong please, I’m still learning too!

  10. It doesn’t do anything in Internet Explorer 9 except show just one image. How do you get it to rotate in Internet Explorer 9?

    • I created a conditional IE statement and created a separate slideshow with a “-ie” class and used the bgStretcher jQuery plugin to drive the same images. It creates a slideshow that looks exactly like the CSS3 one! It’s awesome.

  11. This is a beautiful script, love smoothness of the simple fading transitions. I have one problem that I wondered if someone might be able help with – the background slideshow does not work in Firefox on OSX. It works fine in Firefox on PC however. Any clues as to why this might be? Many thanks.

  12. that’s not use js any thing?, thats so beatiful, i’m bookmark so,,, ^^

  13. Very, very nice, liking this a lot!

    Is there anyway to add the pattern onto the images, yet still below the headlines, any other way than using pseudo-element :after? The reason I am asking is that I can’t use jquery to manipulate the background value.

  14. it’s very cool. i love this tutorial.
    Anyway it’s has a little problem that i need your solution.
    when start Slide in browser it’s perfectly slides and perfectly loop but when i switch to another tab(same browser) for see something and back to Slide it will be messy slide. I already test with your original Demo it’s show the same results.

    Do you have any solution for this. Thanks you very much.^^

  15. Hi, I just want to know how did you adjust the image for all type and size of screen ?
    Thanks,
    Louis

  16. Hello,

    I didn’t follow the discussion among all seven pages, so I don’t know know if it’s already been asked, but… how do you show only the first image, instead of the last image (if css3 ist still not supported in explorer and you have to fix that with modernizr)? Do I have to change something in the CSS, HTML Code oder Do I have to generate a new JavaScript with modernizr?

    Thanks for helping!

  17. Please tell me, what an amazing programm and settings do you use to compress images in background (50-80 kb!!!) I can’t get less then 240 kb for my pictures.

  18. Hi
    I love this tutorial but I have a question. I would like to have a single image fade in (demo1) with txt and then stay there. How do I edit the css and the html so that it only displays the first image and the first text and they both stay there?

    Im not a web designer but a photographer so im sorry if none of this make sense.

    M

    • @Jaeger Jensen, for my site i changed in:

      style1.css

      .cb-slideshow li span {

      these lines:

      -webkit-backface-visibility: hidden;
      -webkit-animation: imageAnimation 240s linear infinite 2s;
      -moz-animation: imageAnimation 240s linear infinite 2s;
      -o-animation: imageAnimation 240s linear infinite 2s;
      -ms-animation: imageAnimation 240s linear infinite 2s;
      animation: imageAnimation 240s linear infinite 2s;
      }
      .cb-slideshow li div {

      these lines:

      -webkit-animation: titleAnimation 90s linear infinite 15s;
      -moz-animation: titleAnimation 90s linear infinite 15s;
      -o-animation: titleAnimation 90s linear infinite 15s;
      -ms-animation: titleAnimation 90s linear infinite 15s;
      animation: titleAnimation 90s linear infinite 15s;
      }

      index.html:

      leave only this lines:

      Image 01Deleting lines for Image 02,03,04,05,06

    • in style1.css leave lines only for 1.jpg:

      .cb-slideshow li:nth-child(1) span {
      background-image: url(../images/1.jpg)
      }
      and delete similar lines: .cb-slideshow li:nth-child(2,3,4,5,6) span {
      background-image: url(../images/2,3,4,5,6.jpg)
      }

  19. As a couple other have mentioned …

    If you reduce the slide count to 3-4 for example you get 6 second periods of black between slides. If you expand the slide count to a larger number than 6 (esp 15-20) you get overlapping images sometimes both visible at the same time seen easily at the start of the slideshow after a full cycle.

    Curious is anyone or the codes author has a thought on this? A shame, because like most items on codrops it’s a great piece of code for those of us getting out hands on CSS3! Thank you.

    • Solved my own observation, thought I would share for any others making the mistake!! In short, since the example has 6 images set on 6 second delays, it’s easy to confuse the numbers when calculating the keyframe percentages. Be sure to use the individual time interval divided by the total time interval then continue the splitting, etc. as instructed. In this way the percentages for keyframe change %’s will vary depending on your slide count (as the other way it does not) & the overlapping transition effects work perfectly whether you have 3 slides or 30!

  20. I just wanted to know how to calculate the slide animation. I am reading the thread. I got 13 pictures. I got it 6 second interval equals to 80 seconds. but my letters are overlapping. Please do help. Thank you

  21. This looks awesome! However, I can’t manage to integrate it into my wordpress theme.

  22. I don’t know if you have seen this, but when you remove the focus from the page, and put it back, the backgrounds go crazy. They are overlapping and most of time showing just white background. Are you familiar with this and do you have maybe a solution?
    Tnx in advance! Cheers! Great tutorial btw…

    • Hi Filip,
      yes it’s really sad, this seems to happen in the new versions of Google Chrome (19.0.1084.56/Win) and Safari (5.1.5/Win) so it seems to be a WebKit problem. In Firefox this doesn’t happen. Let’s just hope that it get’s fixed with the new versions. If I find some fix in the meantime, I’ll post it here. Thank you for your feedback! Cheers, ML

  23. Is there a way to where I could get it so on click, say clicking a menubar option such as “Home”, to make it change to a certain image and stay on that image till another menubar option is clicked such as “About Us”?

  24. I have a question
    How do I make this slide not stay as background but as a div?
    so I can roll it

  25. is it posible to change the color from white when it change the image background to on other?