v2.0.0-next.0
Pre-releaseBreaking changes
This is a breaking change release, you'll need to migrate your existing code if you upgrade from the v1.
Why a breaking change release ?
More modern
The web has come a long way since Scrollable-Component has been originally designed (June 2020).
The following CSS rules are now widely supported (thanks to Edge transitioning to Chromium):
::part()
to customize parts of a web componentposition: sticky;
to create fixed overlay within a viewportdisplay: grid;
to ease layout creation
And the following JS features are becoming widely supported:
ResizeObserverEntry
to ease bounding box computation (still waiting for Safari to catch up on this one)Private class fields
to improve code cleanliness
New design
This version aims to fix several design flaws inherent to the v1:
-
Make the root element of the component the viewport itself
- It allows you to directly interact with it as a native viewport instead of targeting a child element
- It allows you to fallback to a native viewport when the JS is disabled or while the page hasn't finished loading yet
-
Make the custom scrollbars part of the viewport
- Before, when using your scroll wheel while hovering a custom scrollbar, nothing would have happened
- Now, it scrolls the viewport like a native scrollbar
-
Remove almost all of the CSS properties in favor of the
::part()
pseudo element- It allows you to directly apply your own CSS rules to any parts of the components without any restriction
- It improves the maintainability of the code, as no additionnal CSS properties will be required in order to increase the customizability of the component
- It reduces the weight of the component
-
Make the component sizing more predictable
- When sizing/positioning the component absolutely, in some cases, it would have resulted differently from a native viewport rendering, not shrinking or growing like we would expect it to
- Although the new design still has some differences compared to native viewports, it's now easier to size and position (even easier than native viewports in some cases, e.g. horizontal carrousel)
New Features
In addition to this new design elements, there is some new features.
-
You can now use CSS
::part()
to further customize the component- use
::part(content)
to target the content of the viewport - use
::part(scrollbar)
to target both scrollbars - use
::part(scrollbar-track)
to target both scrollbar tracks - use
::part(scrollbar-thumb)
to target both scrollbar thumbs - use
::part(vertical-scrollbar)
to target the vertical scrollbar - use
::part(vertical-scrollbar-track)
to target the vertical scrollbar track - use
::part(vertical-scrollbar-thumb)
to target the vertical scrollbar thumb - use
::part(horizontal-scrollbar)
to target the horizontal scrollbar - use
::part(horizontal-scrollbar-track)
to target the horizontal scrollbar track - use
::part(horizontal-scrollbar-thumb)
to target the horizontal scrollbar thumb - use
::part(active)
to target the active scrollbar thumb (when you drag the scrollbar thumb) - CSS parts can be combined with the
:hover
pseudo-selector & the:before
&:after
pseudo-elements
- use
-
New CSS properties
--scrollbar-thumb-fill-color-active
to set the background color of the scrollbar thumb when it's active--scrollbar-z-index
to set the z-index of both scrollbars
-
You can now add the
edge-detection="true"
attribute to detect when the viewport is fully scrolled to one of its edges- When there is vertical overflow:
- Adds a
top-overflow
class when the viewport can be scrolled up, removes it when fully scrolled to the top - Adds a
bottom-overflow
class when the viewport can be scrolled down, removes it when fully scrolled to the bottom
- Adds a
- When there is horizontal overflow:
- Adds a
left-overflow
class when the viewport can be scrolled left, removes it when fully scrolled to the left - Adds a
right-overflow
class when the viewport can be scrolled right, removes it when fully scrolled to the right
- Adds a
- When there is vertical overflow:
-
You can now add the
scrollbar-overlay="false"
attribute to make the scrollbars part of the content (like most of the native scrollbars on desktop) instead of them being on top of the content (like most of the native scrollbars on smartphones)- When the viewport is overflowing, the scrollbar reduces the place available for the content
- When the viewport is not overflowing, the scrollbar takes no place
Migration guide
Build optimizer
Some build optimizers may require you to target esnext
(angular/angular-cli#22486)es2022
.
The viewport
and content
component properties have been removed
As the component now is the viewport itself, you can still use the JavaScript API to interact with it:
const scrollableComponent = document.querySelector('scrollable-component');
// v1 - Before the migration
scrollableComponent.viewport.addEventListener('scroll', (event) => {
// Your code
});
// v2 - After the migration
scrollableComponent.addEventListener('scroll', (event) => {
// Your code
});
Most of the CSS properties have been removed
Removed all the --*-z-index
CSS properties, except --scrollbar-z-index-hover
/* v1 - Before */
scrollable-component {
--viewport-z-index: 0;
--horizontal-scrollbar-z-index: 10;
--vertical-scrollbar-z-index: 20;
--scrollbar-z-index-hover: 30;
}
/* v2 - After */
scrollable-component {
--content-z-index: 0;
--scrollbar-z-index: 10;
--scrollbar-z-index-hover: 20;
}
Removed all the --viewport-*
CSS properties
/* v1 - Before */
scrollable-component {
--viewport-overflow-x: auto;
--viewport-overflow-y: auto;
--viewport-scroll-snap-type: none;
--viewport-scroll-behavior: auto;
--viewport-overscroll-behavior: auto;
--viewport-z-index: 0;
}
/* v2 - After */
scrollable-component {
overflow-x: auto;
overflow-y: auto;
scroll-snap-type: none;
scroll-behavior: auto;
overscroll-behavior: auto;
/* `--viewport-z-index` has been replaced by `--content-z-index` */
}
Removed all the --vertical-scrollbar-*
CSS properties
/* v1 - Before */
scrollable-component {
--vertical-scrollbar-padding: var(--scrollbar-padding);
--vertical-scrollbar-background: none;
--vertical-scrollbar-background-size: auto;
--vertical-scrollbar-z-index: 20;
--vertical-scrollbar-track-background: none;
--vertical-scrollbar-track-background-size: auto;
--vertical-scrollbar-thumb-background: none;
--vertical-scrollbar-thumb-background-size: auto;
}
/* v2 - After */
scrollable-component::part(vertical-scrollbar) {
padding: var(--scrollbar-padding);
background: none;
background-size: auto;
/* z-index has no effect here, use `--scrollbar-z-index` & `--scrollbar-z-index-hover` instead */
}
scrollable-component::part(vertical-scrollbar-track) {
background: none;
background-size: auto;
}
scrollable-component::part(vertical-scrollbar-thumb) {
background: none;
background-size: auto;
}
Removed all the --horizontal-scrollbar-*
CSS properties
/* v1 - Before */
scrollable-component {
--horizontal-scrollbar-padding: var(--scrollbar-padding);
--horizontal-scrollbar-background: none;
--horizontal-scrollbar-background-size: auto;
--horizontal-scrollbar-z-index: 10;
--horizontal-scrollbar-track-background: none;
--horizontal-scrollbar-track-background-size: auto;
--horizontal-scrollbar-thumb-background: none;
--horizontal-scrollbar-thumb-background-size: auto;
}
/* v2 - After */
scrollable-component::part(horizontal-scrollbar) {
padding: var(--scrollbar-padding);
background: none;
background-size: auto;
/* z-index has no effect here, use --scrollbar-z-index & --scrollbar-z-index-hover instead */
}
scrollable-component::part(horizontal-scrollbar-track) {
background: none;
background-size: auto;
}
scrollable-component::part(horizontal-scrollbar-thumb) {
background: none;
background-size: auto;
}
Removed all the --scrollbar-*
CSS properties, except:
--scrollbar-width
--scrollbar-padding
--scrollbar-z-index
--scrollbar-z-index-hover
--scrollbar-track-fill-color
--scrollbar-track-fill-color-hover
--scrollbar-thumb-fill-color
--scrollbar-thumb-fill-color-hover
--scrollbar-thumb-fill-color-active
/* v1 - Before */
scrollable-component {
--scrollbar-fill-color: transparent;
--scrollbar-fill-color-hover: transparent;
--scrollbar-border-width: 0;
--scrollbar-border-style: none;
--scrollbar-border-color: #999;
--scrollbar-border-radius: 0;
--scrollbar-box-shadow: none;
--scrollbar-track-border-width: 0;
--scrollbar-track-border-style: none;
--scrollbar-track-border-color: #999;
--scrollbar-track-border-radius: 0;
--scrollbar-track-box-shadow: none;
--scrollbar-thumb-border-width: 0;
--scrollbar-thumb-border-style: none;
--scrollbar-thumb-border-color: #999;
--scrollbar-thumb-border-radius: var(--scrollbar-width);
--scrollbar-thumb-box-shadow: none;
}
/* v2 - After */
scrollable-component::part(scrollbar) {
background-color: transparent;
border-width: 0;
border-style: none;
border-color: #999;
border-radius: 0;
box-shadow: none;
}
scrollable-component::part(scrollbar):hover {
background-color: transparent;
}
scrollable-component::part(scrollbar-track) {
border-width: 0;
border-style: none;
border-color: #999;
border-radius: 0;
box-shadow: none;
}
scrollable-component::part(scrollbar-thumb) {
border-width: 0;
border-style: none;
border-color: #999;
border-radius: var(--scrollbar-width);
box-shadow: none;
}