{"id":283200,"date":"2019-03-07T08:26:59","date_gmt":"2019-03-07T15:26:59","guid":{"rendered":"http:\/\/css-tricks.com\/?p=283200"},"modified":"2020-01-30T17:28:08","modified_gmt":"2020-01-31T00:28:08","slug":"styling-based-on-scroll-position","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/styling-based-on-scroll-position\/","title":{"rendered":"Styling Based on Scroll Position"},"content":{"rendered":"

Rik Schennink documents<\/a> a system for being able to write CSS selectors that style a page when it has scrolled to a certain point. If you’re like me, you’re already on the lookout for document.addEventListener('scroll' ...<\/code> and being terrified about performance. Rik gets to that right away by both debouncing<\/a> the function as well as marking the event as passive<\/code>.<\/p>\n

<\/p>\n

The end result is a data-scroll<\/code> attribute on the <html><\/code> element that can be used in the CSS. Meaning if you’re scrolled to 640px down the page, you have <html data-scroll=\"640\"><\/code> and could write a selector like:<\/p>\n

html:not([data-scroll='0']) {\r\n  padding-top: 3em;\r\n}\r\nhtml:not([data-scroll='0']) header {\r\n  position: fixed;\r\n}<\/code><\/pre>\n

\n See the Pen
\n Writing Dumb JS 🧟‍♂️ and Smart CSS 👩‍🔬<\/a> by Rik Schennink (
@rikschennink<\/a>)
\n on
CodePen<\/a>.<\/span>\n<\/p>\n

Unfortunately, we don’t have greater than (><\/code>) less than (<<\/code>) selectors in CSS for things like numbered attributes, so the CSS styling potential is fairly limited here. You might ultimately need to update the JavaScript function such that it applies other classes or data attributes based on your math. But you’ll already be set up for good performance here.<\/p>\n

“Apply styles when the user has scrolled away from the top”<\/em> is a legit use case. It makes me think of a once function<\/a> (like we have in jQuery<\/a>) where any scroll event would only be triggered once and then not again. They scrolled! So, by definition, they aren’t at the top anymore! But that doesn’t deal with when they scroll back<\/em> to the top. <\/p>\n

I find it generally more useful to use IntersectionObserver<\/code> for styling things based on scroll position. With it, you can do things like, “has this element been scrolled into view or beyond,” which is generically useful and can be used for scrolled-away-from-top stuff too. <\/p>\n

Here’s an example that adds or removes a class if a user has scrolled past a hidden pixel positioned at 500px down the page.<\/p>\n

\n See the Pen
\n Fixed Header with IntersectionObserver<\/a> by Chris Coyier (
@chriscoyier<\/a>)
\n on
CodePen<\/a>.<\/span>\n<\/p>\n

That’s performant as well, avoiding any scroll event handlers at all.<\/p>\n

And speaking of IntersectionObserver<\/code>, check out “Trust is Good, Observation is Better\u2014Intersection Observer v2”<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"

Rik Schennink documents a system for being able to write CSS selectors that style a page when it has scrolled […]<\/p>\n","protected":false},"author":3,"featured_media":269896,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"inline_featured_image":false,"c2c_always_allow_admin_comments":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"A couple of quick and different ways to style things based on scroll position.","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_share_on_mastodon":"0","_share_on_mastodon_status":"%title% %permalink%"},"categories":[4],"tags":[1599,1598,674,432,754],"class_list":["post-283200","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-articles","tag-attribute-selectors","tag-data-attributes","tag-debounce","tag-javascript","tag-scrolling"],"acf":{"show_toc":"No"},"share_on_mastodon":{"url":"","error":""},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/04\/higher-order-components.jpg?fit=1200%2C600&ssl=1","jetpack-related-posts":[{"id":13465,"url":"https:\/\/css-tricks.com\/persistent-headers\/","url_meta":{"origin":283200,"position":0},"title":"Persistent Headers","author":"Chris Coyier","date":"August 14, 2011","format":false,"excerpt":"This is some code to get the header of some content area to stay visible at the top of the screen as you scroll through that content. Then go away when you've scrolled past that relevant section. Header... persisting. Couple things to know before we get started: There are many\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2011\/08\/persistentheader.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2011\/08\/persistentheader.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2011\/08\/persistentheader.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2011\/08\/persistentheader.jpg?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":20803,"url":"https:\/\/css-tricks.com\/slide-in-as-you-scroll-down-boxes\/","url_meta":{"origin":283200,"position":1},"title":"Slide In (as you scroll down) Boxes","author":"Chris Coyier","date":"March 27, 2013","format":false,"excerpt":"I was playing with my new Nexus 7 (I really wanted to own a real Android device) and I noticed a neat little effect in the Google+ app that comes with it. As you swipe down, new modules of content slide up into place. Video is best here: We can\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":383910,"url":"https:\/\/css-tricks.com\/chrome-133-goodies\/","url_meta":{"origin":283200,"position":2},"title":"Chrome 133 Goodies","author":"Geoff Graham","date":"January 31, 2025","format":false,"excerpt":"Did you see the release notes for Chrome 133? It's currently in beta, but the Chrome team has been publishing a slew of new articles with pretty incredible demos that are tough to ignore. I figured I'd round those up in one place.","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/chrome-browser-extension-blueprint.jpg?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/chrome-browser-extension-blueprint.jpg?fit=1200%2C600&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/chrome-browser-extension-blueprint.jpg?fit=1200%2C600&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/chrome-browser-extension-blueprint.jpg?fit=1200%2C600&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2018\/09\/chrome-browser-extension-blueprint.jpg?fit=1200%2C600&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":352754,"url":"https:\/\/css-tricks.com\/scroll-shadows-with-javascript\/","url_meta":{"origin":283200,"position":3},"title":"Scroll Shadows With JavaScript","author":"Chris Coyier","date":"October 5, 2021","format":false,"excerpt":"Scroll shadows are when you can see a little inset shadow on elements if (and only if) you can scroll in that direction. It's just good UX. You can actually pull it off in CSS, which I think is amazing and one of the great CSS tricks. Except... it just\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen_Shot_2021-09-05_at_9.52.01_AM.webp?fit=1200%2C920&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen_Shot_2021-09-05_at_9.52.01_AM.webp?fit=1200%2C920&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen_Shot_2021-09-05_at_9.52.01_AM.webp?fit=1200%2C920&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen_Shot_2021-09-05_at_9.52.01_AM.webp?fit=1200%2C920&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2021\/09\/Screen_Shot_2021-09-05_at_9.52.01_AM.webp?fit=1200%2C920&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":330827,"url":"https:\/\/css-tricks.com\/how-to-use-the-locomotive-scroll-for-all-kinds-of-scrolling-effects\/","url_meta":{"origin":283200,"position":4},"title":"How to Use the Locomotive Scroll for all Kinds of Scrolling Effects","author":"King Nelson","date":"December 16, 2020","format":false,"excerpt":"I was recently looking for a way to perform scrolling effects on a project and I stumbled on the Locomotive Scroll library. It lets you perform a variety of scrolling effects, like parallax and triggering\/controlling animations at scroll points. You might also call it a \u201csmooth scrolling\u201d library, but it\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/09\/scroll-to-top.png?fit=1200%2C600&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/09\/scroll-to-top.png?fit=1200%2C600&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/09\/scroll-to-top.png?fit=1200%2C600&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/09\/scroll-to-top.png?fit=1200%2C600&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/css-tricks.com\/wp-content\/uploads\/2020\/09\/scroll-to-top.png?fit=1200%2C600&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":206340,"url":"https:\/\/css-tricks.com\/scroll-drawing\/","url_meta":{"origin":283200,"position":5},"title":"Scroll Drawing","author":"Chris Coyier","date":"August 10, 2015","format":false,"excerpt":"We've taken an in-depth look at how SVG line drawing works before. It's a clever trick where you use dashed lines for the stroke, but the gap in the dash is so long it covers the entire path. Then you can move it such that it covers the entire path\u2026","rel":"","context":"In "Articles"","block_context":{"text":"Articles","link":"https:\/\/css-tricks.com\/category\/articles\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/283200","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/comments?post=283200"}],"version-history":[{"count":8,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/283200\/revisions"}],"predecessor-version":[{"id":303013,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/posts\/283200\/revisions\/303013"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media\/269896"}],"wp:attachment":[{"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/media?parent=283200"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/categories?post=283200"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/css-tricks.com\/wp-json\/wp\/v2\/tags?post=283200"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}