80

I have been looking for a way to scroll down when clicking on a button that is located on top of a page using CSS3 only.

So I've found this tutorial: http://tympanus.net/codrops/2012/06/12/css-only-responsive-layout-with-smooth-transitions/

Demo: http://tympanus.net/Tutorials/SmoothTransitionsResponsiveLayout/

But it's a bit too advanced for my needs since I just want the browser to scroll down on a click on one button located on top of the page, so I was wondering: is it possible to do those CSS scrolls without the input buttons, just with an anchor tag?

HTML looks like this: <a href="#" class="button">Learn more</a>

I have already some CSS which I need to trigger on button click:

/* Button animation tryout. */
.animate {
    animation: moveDown 0.6s ease-in-out 0.2s backwards;
}
@keyframes moveDown{
    0% { 
        transform: translateY(-40px); 
        opacity: 0;
    }
    100% { 
        transform: translateY(0px);  
        opacity: 1;
    }
}
leonheess
  • 16,068
  • 14
  • 77
  • 112
blameless75
  • 2,148
  • 2
  • 19
  • 14
  • 7
    A major drawback of this CSS-based scrolling is that the user can't manually scroll *up* after using the CSS-based scrolling has scrolled down to a selected element. Seems like a user would intuitively want to do this, given the animated page transition! For me it's back to jQuery's animate({scrollTop:...}). Or did I miss something? – vicmortelmans Dec 28 '14 at 22:14
  • 1
    With [this solution](https://github.com/webdevelopers-eu/DNA-Parallax) you can fix the inability to go back. Just use this HTML markup: `
    ...
    ` And it will move down as you scroll down and back up as you scroll up...
    – elixon Feb 13 '19 at 20:57

4 Answers4

124

Use anchor links and the scroll-behavior property (MDN reference) for the scrolling container:

scroll-behavior: smooth;

Browser support: Firefox 36+, Chrome 61+ (therefore also Edge 79+), Safari 15.4+, Opera 48+.

Intenet Explorer, non-Chromium Edge and older versions of Safari (that are still used by some users) do not support scroll-behavior and simply "jump" to the link target (graceful degradation).

Example usage:

<head>
  <style type="text/css">
    html {
      scroll-behavior: smooth;
    }
  </style>
</head>
<body id="body">
  <a href="#foo">Go to foo!</a>
  
  <!-- Some content -->
  
  <div id="foo">That's foo.</div>
  <a href="#body">Back to top</a>
</body>

Here's a Fiddle.

And here's also a Fiddle with both horizontal and vertical scrolling.

Felix Edelmann
  • 4,959
  • 3
  • 28
  • 34
  • 9
    Why downvote? Could you please explain how I could improve my answer or why my solution isn't good? – Felix Edelmann May 22 '16 at 21:43
  • Only works with vertical page scrolling, as opposed to horizontal element scrolling, in my Firefox 46 on Windows. What I mean is that it does move things into place, no problem there, but there is no animation. Vertical scrolling includes animation though. Rather peculiar that given how much advanced code there is in a modern browser, Mozilla engineers were either unwilling or unable to implement scrolling animation for horizontal scrolling. – Armen Michaeli May 23 '16 at 14:10
  • 1
    I actually never thought about horizontal scrolling. But as you can see in this fiddle: http://jsfiddle.net/1Lfybv56/2/ it works as well – also with both horizontal and vertical scrolling. The only difference I discovered: With horizontal scrolling, anchor links to name="..." tags don't work, you have to use id="...". – Felix Edelmann May 23 '16 at 17:17
  • 3
    You're getting downvoted because at http://caniuse.com/#search=scroll-behavior it says it only works in firefox. So it is essentially worthless for production level sites since it only works in one browser that isn't even the most used. UNLESS, the traffic on your site is mostly firefox. – MeanMatt Dec 02 '16 at 22:00
  • 2
    Jesus's solution is really nice, but I'm adding to Felix's answer as it works in Chrome v62, Firefox v57 and is under consideration in Edge (no support yet in Safari), and we want to put pressure on browser manufacturers. So this is what I give my students as a simple example for those browsers, also with smooth scrolling "top" links: https://daveeveritt.github.io/css-smooth-scroll/ The repo is here with more info and links in the readme: https://github.com/DaveEveritt/css-smooth-scroll – Dave Everitt Jan 25 '18 at 21:15
  • 1
    It works in all but extremely archaic versions of Chrome and Firefox, as well as the Samsung Browser. On all my sites the non-supported versions of these browsers make up a negligible portion of market share as of me writing this comment. The concern here is mainly lack of support in Safari and to some degree, IE and Edge. However...given how elegant it is and how this is a non-essential feature, this answer may be appealing to a lot of people (it's appealing to me for this reason.) – cazort Mar 05 '19 at 22:36
  • How is this achieved by targeting just ONE element vs the entire HTML document? – Birdie Golden Jul 30 '19 at 15:29
92

You can do it with anchor tags using css3 :target pseudo-selector, this selector is going to be triggered when the element with the same id as the hash of the current URL get an match. Example

Knowing this, we can combine this technique with the use of proximity selectors like "+" and "~" to select any other element through the target element who id get match with the hash of the current url. An example of this would be something like what you are asking.

Jesus Bejarano
  • 1,146
  • 10
  • 9
  • Thanks Jesus. One question through: the scrolled slides have to be in a tag like the `
  • ` elements to contain the three menus? = is it eventually possible to scroll the page itself?
  • – blameless75 Jul 18 '13 at 00:04
  • I'm taking an example: on the [Twitter Bootstrap page](http://twitter.github.io/bootstrap/) is it say possible to make it so that when you click on the blue button it scrolls to the description on the bottom? – blameless75 Jul 18 '13 at 00:05
  • I have found a way to do that via a [simple JS script](http://www.itnewb.com/tutorial/Creating-the-Smooth-Scroll-Effect-with-JavaScript), I think I'll stick with that. ;) – blameless75 Jul 18 '13 at 00:10
  • 5
    You can use the target technique to target any element in the layout, even the page itself selecting the '' tag :). – Jesus Bejarano Jul 21 '13 at 03:19
  • @JesusBejarano: Why do you use selector a[ id= "servicios" ] instead of simple a#servicios? Is that for a reason or just a _moment of stupidity_ (no offense)? – Radek Pech Dec 05 '13 at 09:56
  • 1
    Nothing special really, one could use one way or the other, i never use "#" selector in my scss files, i rather target classes and attributes, is just matter of preference. Since i would never use that keyword, my mind just throw the attribute selector to target the id attribute instead doing it the simple way :). – Jesus Bejarano Dec 14 '13 at 02:24
  • 2
    say, why do we need the `backface-visibility` in the later demo? we're not flipping anything... – Eliran Malka Feb 19 '14 at 20:04
  • 1
    At the time was planning to show different examples (one was a cube), but i thought that it would be better only show the most simple one for the sake of the answer, and i leave the rule that would make every example work in the parent selector, and i forgot to remove it for this specific example. In others, word you can remove the backface-visibility without worries. Cheers :) – Jesus Bejarano Feb 19 '14 at 21:43
  • 17
    For anyone else wanting to see the minimum necessary for this animation, I took out formatting etc to make it a bit easier to work out what does what http://jsfiddle.net/YYPKM/347/ – Louis Maddox Apr 30 '14 at 15:37
  • 3
    As I assume it is not possible to be flexible here, right? The transform needs a real value and cannot be targeted to another element, right? – Keenora Fluffball Feb 03 '15 at 14:03
  • As Keenora asked--do we need to know the div's height before hand? – Taylor C. White Jul 15 '15 at 03:16
  • 2
    @LouisMaddox Adding `header { position: fixed; left: 0; top: 0; z-index: 10; }` in the css of your fiddle will ensure that the links will always be clickable, because right now, clicking number 2 will make number 1 unclickable. – Gellie Ann Jul 14 '17 at 09:01