Skip to content

Commit

Permalink
Refactor to make the root element the viewport itself
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien-Marcou committed Feb 20, 2022
1 parent aff802e commit a78bb18
Show file tree
Hide file tree
Showing 4 changed files with 272 additions and 235 deletions.
2 changes: 0 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
export class ScrollableComponentElement extends HTMLElement {
public readonly viewport: HTMLElement;
public readonly content: HTMLElement;
}

declare global {
Expand Down
285 changes: 139 additions & 146 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,210 +2,203 @@
box-sizing: border-box;
}
:host {
--fade-in-transition-duration: 150ms;
--fade-out-transition-duration: 800ms;
--fade-out-transition-delay: 300ms;
--fill-color-transition-duration: 150ms;

--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;

--scrollbar-width: 16px;
--scrollbar-padding: 2px;
--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-z-index-hover: 30;
--vertical-scrollbar-padding: var(--scrollbar-padding);
--vertical-scrollbar-background: none;
--vertical-scrollbar-background-size: auto;
--vertical-scrollbar-z-index: 20;
--horizontal-scrollbar-padding: var(--scrollbar-padding);
--horizontal-scrollbar-background: none;
--horizontal-scrollbar-background-size: auto;
--horizontal-scrollbar-z-index: 10;

--scrollbar-track-fill-color: transparent;
--scrollbar-track-fill-color-hover: transparent;
--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;
--vertical-scrollbar-track-background: none;
--vertical-scrollbar-track-background-size: auto;
--horizontal-scrollbar-track-background: none;
--horizontal-scrollbar-track-background-size: auto;
--scrollbar-track-fill-color-hover: var(--scrollbar-track-fill-color);

--scrollbar-thumb-fill-color: #ccc;
--scrollbar-thumb-fill-color-hover: #aaa;
--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;
--vertical-scrollbar-thumb-background: none;
--vertical-scrollbar-thumb-background-size: auto;
--horizontal-scrollbar-thumb-background: none;
--horizontal-scrollbar-thumb-background-size: auto;
--scrollbar-thumb-fill-color-active: var(--scrollbar-thumb-fill-color-hover);

--content-padding: 0;

position: relative;
overflow: hidden;
display: grid;
grid-template: 1fr / 1fr;
}
--content-z-index: 0;
--scrollbar-z-index: 10;
--scrollbar-z-index-hover: 20;

--fade-in-transition-duration: 150ms;
--fade-out-transition-duration: 800ms;
--fade-out-transition-delay: 300ms;
--fill-color-transition-duration: 150ms;

/* Viewport */
.viewport {
z-index: var(--viewport-z-index);
display: grid;
overflow-x: var(--viewport-overflow-x);
overflow-y: var(--viewport-overflow-y);
--content-column-width: 1fr;
--content-row-height: 1fr;

contain: content;
display: grid !important;
padding: 0 !important;
grid-template-columns: var(--content-column-width) 0;
grid-template-rows: var(--content-row-height) 0;
overflow: auto;
scrollbar-width: none;
outline: none;
scroll-behavior: var(--viewport-scroll-behavior);
overscroll-behavior: var(--viewport-overscroll-behavior);
scroll-snap-type: var(--viewport-scroll-snap-type);
}
.viewport::-webkit-scrollbar {
:host::-webkit-scrollbar {
width: 0;
height: 0;
}
:host([hidden]) {
display: none !important;
}
:host(.overflow-x-hidden) {
--content-column-width: 100%;
}
:host(.overflow-y-hidden) {
--content-row-height: 100%;
}

/* Content */
.content-wrapper {
z-index: var(--content-z-index);
display: flex;
flex-direction: column;
grid-area: 1 / 1;
}
.content {
flex-grow: 1;
padding: var(--content-padding);
}
.content.restrict-width {
width: var(--viewport-width);

/* Scrollbar's wrapper */
.scrollbar-wrapper {
z-index: var(--scrollbar-z-index);
position: sticky;
}
.content.restrict-height {
height: var(--viewport-height);
.scrollbar-wrapper:hover {
z-index: var(--scrollbar-z-index-hover);
}
.vertical-scrollbar-wrapper {
grid-area: 1 / 2;
top: 0;
right: 0;
width: 0;
height: 0;
}
.horizontal-scrollbar-wrapper {
grid-area: 2 / 1;
bottom: 0;
left: 0;
width: 0;
height: 0;
}

/* Scrollbar */
.scrollbar {
contain: strict;
user-select: none;
touch-action: none;
position: absolute;
border-width: var(--scrollbar-border-width);
border-style: var(--scrollbar-border-style);
border-color: var(--scrollbar-border-color);
border-radius: var(--scrollbar-border-radius);
box-shadow: var(--scrollbar-box-shadow);
opacity: 0;
padding: var(--scrollbar-padding);
transform: translate3d(0, 0, 0);
transition: opacity var(--fade-out-transition-duration) ease-in-out var(--fade-out-transition-delay), background-color var(--fill-color-transition-duration) ease-out;
}
.vertical-scrollbar {
z-index: var(--vertical-scrollbar-z-index);
width: var(--scrollbar-width);
right: 0;
top: 0;
bottom: 0;
padding: var(--vertical-scrollbar-padding);
background: var(--vertical-scrollbar-background);
background-color: var(--scrollbar-fill-color);
background-size: var(--vertical-scrollbar-background-size);
}
.vertical-scrollbar.left-position {
left: 0;
right: auto;
right: 0;
width: var(--scrollbar-width);
height: var(--viewport-height);
}
.horizontal-scrollbar {
z-index: var(--horizontal-scrollbar-z-index);
height: var(--scrollbar-width);
left: 0;
right: 0;
bottom: 0;
padding: var(--horizontal-scrollbar-padding);
background: var(--horizontal-scrollbar-background);
background-color: var(--scrollbar-fill-color);
background-size: var(--horizontal-scrollbar-background-size);
}
.horizontal-scrollbar.top-position {
top: 0;
bottom: auto;
left: 0;
height: var(--scrollbar-width);
width: var(--viewport-width);
}
.scrollbar:hover,
.scrollbar.scrolling-with-thumb,
.viewport:hover ~ .scrollbar,
.viewport:not(:focus):focus-within ~ .scrollbar,
.viewport.touch ~ .scrollbar {
:host(:hover) .scrollbar,
:host(:focus-within) .scrollbar,
:host(.touch) .scrollbar {
opacity: 1;
transition: opacity var(--fade-in-transition-duration) ease-in-out 0s, background-color var(--fill-color-transition-duration) ease-out;
}
.viewport.scrollbar-visible ~ .scrollbar {
opacity: 1;
transition: none;
}
.scrollbar:hover,
.scrollbar.scrolling-with-thumb {
z-index: var(--scrollbar-z-index-hover);
background-color: var(--scrollbar-fill-color-hover);
}
.scrollbar.hidden {
display: none;
}
.scrollbar .scrollbar-track {
height: 100%;
width: 100%;
border-width: var(--scrollbar-track-border-width);
border-style: var(--scrollbar-track-border-style);
border-color: var(--scrollbar-track-border-color);
border-radius: var(--scrollbar-track-border-radius);
box-shadow: var(--scrollbar-track-box-shadow);
transition: background-color var(--fill-color-transition-duration) ease-out;
}

/* Scrollbar's strack */
.vertical-scrollbar .scrollbar-track {
background: var(--vertical-scrollbar-track-background);
background-color: var(--scrollbar-track-fill-color);
background-size: var(--vertical-scrollbar-track-background-size);
}
.horizontal-scrollbar .scrollbar-track {
background: var(--horizontal-scrollbar-track-background);
.scrollbar-track {
height: 100%;
width: 100%;
background-color: var(--scrollbar-track-fill-color);
background-size: var(--horizontal-scrollbar-track-background-size);
border-radius: var(--scrollbar-width);
transition: background-color var(--fill-color-transition-duration) ease-out;
}
.scrollbar-track:hover,
.scrollbar.scrolling-with-thumb .scrollbar-track {
.scrollbar-track:hover {
background-color: var(--scrollbar-track-fill-color-hover);
}

/* Scrollbar's thumb */
.scrollbar .scrollbar-thumb {
.scrollbar-thumb {
height: 100%;
width: 100%;
border-width: var(--scrollbar-thumb-border-width);
border-style: var(--scrollbar-thumb-border-style);
border-color: var(--scrollbar-thumb-border-color);
border-radius: var(--scrollbar-thumb-border-radius);
background-color: var(--scrollbar-thumb-fill-color);
border-radius: var(--scrollbar-width);
transform: translate3d(0, 0, 0);
box-shadow: var(--scrollbar-thumb-box-shadow);
transition: background-color var(--fill-color-transition-duration) ease-out;
}
.vertical-scrollbar .scrollbar-thumb {
background: var(--vertical-scrollbar-thumb-background);
background-color: var(--scrollbar-thumb-fill-color);
background-size: var(--vertical-scrollbar-thumb-background-size);
.scrollbar-thumb:hover {
background-color: var(--scrollbar-thumb-fill-color-hover);
}
.horizontal-scrollbar .scrollbar-thumb {
background: var(--horizontal-scrollbar-thumb-background);
background-color: var(--scrollbar-thumb-fill-color);
background-size: var(--horizontal-scrollbar-thumb-background-size);
.scrollbar-thumb.active {
background-color: var(--scrollbar-thumb-fill-color-active);
}
.scrollbar .scrollbar-thumb:hover,
.scrollbar.scrolling-with-thumb .scrollbar-thumb {
background-color: var(--scrollbar-thumb-fill-color-hover);

/* Scrollbar visibility */
:host([scrollbar-visibility="always"]) .scrollbar {
opacity: 1;
transition: none;
}

/* Vertical scrollbar position */
:host([vertical-scrollbar-position="left"]) {
grid-template-columns: 0 var(--content-column-width);
}
:host([vertical-scrollbar-position="left"]) .content-wrapper,
:host([vertical-scrollbar-position="left"]) .horizontal-scrollbar-wrapper {
grid-column: 2;
}
:host([vertical-scrollbar-position="left"]) .vertical-scrollbar-wrapper {
grid-column: 1;
left: 0;
right: initial;
}
:host([vertical-scrollbar-position="left"]) .vertical-scrollbar {
left: 0;
right: initial;
}

/* Horizontal scrollbar position */
:host([horizontal-scrollbar-position="top"]) {
grid-template-rows: 0 var(--content-row-height);
}
:host([horizontal-scrollbar-position="top"]) .content-wrapper,
:host([horizontal-scrollbar-position="top"]) .vertical-scrollbar-wrapper {
grid-row: 2;
}
:host([horizontal-scrollbar-position="top"]) .horizontal-scrollbar-wrapper {
grid-row: 1;
top: 0;
bottom: initial;
}
:host([horizontal-scrollbar-position="top"]) .horizontal-scrollbar {
top: 0;
bottom: initial;
}

/* Scrollbar overlay */
:host([scrollbar-overlay="false"].horizontal-overflow) .content {
margin-bottom: var(--scrollbar-width);
}
:host([scrollbar-overlay="false"].vertical-overflow) .content {
margin-right: var(--scrollbar-width);
}
:host([scrollbar-overlay="false"][horizontal-scrollbar-position="top"].horizontal-overflow) .content {
margin-top: var(--scrollbar-width);
margin-bottom: 0;
}
:host([scrollbar-overlay="false"][vertical-scrollbar-position="left"].vertical-overflow) .content {
margin-left: var(--scrollbar-width);
margin-right: 0;
}
20 changes: 12 additions & 8 deletions src/index.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
<div class="viewport" tabindex="-1">
<div class="content">
<div class="content-wrapper">
<div class="content" part="content">
<slot></slot>
</div>
</div>
<div class="scrollbar vertical-scrollbar hidden">
<div class="scrollbar-track">
<div class="scrollbar-thumb"></div>
<div class="scrollbar-wrapper horizontal-scrollbar-wrapper">
<div class="scrollbar horizontal-scrollbar hidden" part="scrollbar horizontal-scrollbar">
<div class="scrollbar-track" part="scrollbar-track horizontal-scrollbar-track">
<div class="scrollbar-thumb" part="scrollbar-thumb horizontal-scrollbar-thumb"></div>
</div>
</div>
</div>
<div class="scrollbar horizontal-scrollbar hidden">
<div class="scrollbar-track">
<div class="scrollbar-thumb"></div>
<div class="scrollbar-wrapper vertical-scrollbar-wrapper">
<div class="scrollbar vertical-scrollbar hidden" part="scrollbar vertical-scrollbar">
<div class="scrollbar-track" part="scrollbar-track vertical-scrollbar-track">
<div class="scrollbar-thumb" part="scrollbar-thumb vertical-scrollbar-thumb"></div>
</div>
</div>
</div>
Loading

0 comments on commit a78bb18

Please sign in to comment.