BookStack/resources/sass/_layout.scss
Dan Brown 031067745b
Layout: Restructured tri-layout for sidebar control
Restructured tri-layout grid system, so the sidebars are contained in
their own child grid system, mimicking the parent grid, so we can treat
them as part of the same parent scroll container at smaller screen
sizes for consistent scroll/sticky behavior.

Tested on Firefox, Chromium, Gnome Web and Safari (MacOS).

For #4394
Changes made during review of #4562
2023-10-06 12:03:38 +01:00

512 lines
8.2 KiB
SCSS

/**
* Generic content container
*/
.container {
max-width: $xxl;
margin-inline-start: auto;
margin-inline-end: auto;
padding-inline-start: $-m;
padding-inline-end: $-m;
&.medium {
max-width: 1100px;
}
&.small {
max-width: 840px;
}
&.very-small {
max-width: 480px;
}
}
/**
* Core grid layout system
*/
.grid {
display: grid;
grid-column-gap: $-l;
grid-row-gap: $-l;
> * {
min-width: 0;
}
&.half {
grid-template-columns: 1fr 1fr;
}
&.third {
grid-template-columns: 1fr 1fr 1fr;
}
&.left-focus {
grid-template-columns: 2fr 1fr;
}
&.right-focus {
grid-template-columns: 1fr 3fr;
}
&.gap-y-xs {
grid-row-gap: $-xs;
}
&.gap-xl {
grid-column-gap: $-xl;
grid-row-gap: $-xl;
}
&.gap-xxl {
grid-column-gap: $-xxl;
grid-row-gap: $-xxl;
}
&.v-center {
align-items: center;
}
&.v-end {
align-items: end;
}
&.no-gap {
grid-row-gap: 0;
grid-column-gap: 0;
}
&.no-row-gap {
grid-row-gap: 0;
}
}
@include smaller-than($m) {
.grid.third:not(.no-break) {
grid-template-columns: 1fr 1fr;
}
.grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
grid-template-columns: 1fr;
}
.grid.half.collapse-xs {
grid-template-columns: 1fr 1fr;
}
.grid.gap-xl {
grid-column-gap: $-m;
grid-row-gap: $-m;
}
.grid.right-focus.reverse-collapse > *:nth-child(2) {
order: 0;
}
.grid.right-focus.reverse-collapse > *:nth-child(1) {
order: 1;
}
}
@include smaller-than($s) {
.grid.third:not(.no-break) {
grid-template-columns: 1fr;
}
}
@include smaller-than($xs) {
.grid.half.collapse-xs {
grid-template-columns: 1fr;
}
}
#content {
flex: 1 0 auto;
}
/**
* Flexbox layout system
*/
body.flexbox {
display: flex;
flex-direction: column;
align-items: stretch;
height: 100%;
min-height: 100%;
max-height: 100%;
overflow: hidden;
#content {
flex: 1;
display: flex;
min-height: 0;
}
}
.flex-fill {
display: flex;
align-items: stretch;
min-height: 0;
max-width: 100%;
position: relative;
}
.flex-container-row {
display: flex;
flex-direction: row;
&.v-center {
align-items: center;
}
}
.flex-container-column {
display: flex;
flex-direction: column;
}
.flex-container-row.inline, .flex-container-column.inline {
display: inline-flex !important;
}
.flex-container-column.wrap, .flex-container-row.wrap {
flex-wrap: wrap;
}
.flex {
min-height: 0;
flex: 1;
max-width: 100%;
&.fit-content {
flex-basis: auto;
flex-grow: 0;
}
&.fill-area {
flex-grow: 1;
flex-shrink: 0;
min-width: fit-content;
}
}
.flex-2 {
min-height: 0;
flex: 2;
max-width: 100%;
}
.flex-3 {
min-height: 0;
flex: 3;
max-width: 100%;
}
.flex-none {
flex: none;
}
.justify-flex-start {
justify-content: flex-start;
}
.justify-flex-end {
justify-content: flex-end;
}
.justify-center {
justify-content: center;
}
.justify-space-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
.items-stretch {
align-items: stretch;
}
/**
* Min width utilities
*/
.min-width-xxxxs {
min-width: 60px;
}
.min-width-xxxs {
min-width: 80px;
}
.min-width-xxs {
min-width: 100px;
}
.min-width-xs {
min-width: 120px;
}
.min-width-s {
min-width: 160px;
}
.min-width-m {
min-width: 200px;
}
.min-width-l {
min-width: 240px;
}
.min-width-xl {
min-width: 280px;
}
.min-width-xxl {
min-width: 320px;
}
/**
* Display and float utilities
*/
.block {
display: block !important;
position: relative;
}
.inline {
display: inline !important;
}
.block.inline {
display: inline-block !important;
}
.relative {
position: relative;
}
.fixed {
position: fixed;
z-index: 20;
&.top-right {
top: 0;
right: 0;
}
}
.hidden {
display: none !important;
}
.fill-height {
height: 100%;
}
.float {
float: left;
&.right {
float: right;
}
}
.sticky-top-m {
position: sticky;
top: $-m;
}
/**
* Visibility
*/
@each $sizeLetter, $size in $screen-sizes {
@include smaller-than($size) {
.hide-under-#{$sizeLetter} {
display: none !important;
}
}
@include larger-than($size) {
.hide-over-#{$sizeLetter} {
display: none !important;
}
}
}
[hidden] {
display: none !important;
}
.screen-reader-only {
position: absolute;
inset-inline-start: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
/**
* Border radiuses
*/
.rounded {
border-radius: 4px;
}
/**
* Inline content columns
*/
.dual-column-content {
columns: 2;
}
@include smaller-than($m) {
.dual-column-content {
columns: 1;
}
}
/**
* Fixes
*/
.clearfix::before,
.clearfix::after {
content: " ";
display: table;
}
.clearfix::after {
clear: both;
}
/**
* View Layouts
*/
.tri-layout-container {
display: grid;
margin-inline-start: $-xl;
margin-inline-end: $-xl;
grid-template-columns: 1fr 4fr 1fr;
grid-template-areas: "a b c";
grid-column-gap: $-xl;
position: relative;
}
.tri-layout-sides {
grid-column-start: a;
grid-column-end: c;
grid-row: 1;
min-width: 0;
z-index: 4;
}
.tri-layout-sides-content {
display: grid;
grid-template-areas: "a b c";
grid-template-columns: 1fr 4fr 1fr;
height: 100%;
}
.tri-layout-middle {
grid-area: b;
padding-top: $-m;
min-width: 0;
z-index: 5;
}
.tri-layout-right {
grid-area: c;
min-width: 0;
}
.tri-layout-left {
grid-area: a;
min-width: 0;
}
@include larger-than($xxl) {
.tri-layout-left-contents, .tri-layout-right-contents {
padding: $-xl $-m;
position: sticky;
top: 0;
max-height: 100vh;
min-height: 50vh;
overflow-y: scroll;
overflow-x: hidden;
height: 100%;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
.tri-layout-middle-contents {
max-width: 940px;
margin: 0 auto;
}
}
@include between($xxl, $xxxl) {
.tri-layout-sides-content, .tri-layout-container {
grid-template-columns: 1fr calc(940px + (2 * $-m)) 1fr;
}
.tri-layout-container {
grid-column-gap: $-s;
margin-inline-start: $-m;
margin-inline-end: $-m;
}
}
@include smaller-than($xxl) {
.tri-layout-container {
grid-template-areas: "a b b";
grid-template-columns: 1fr 3fr;
grid-template-rows: min-content min-content 1fr;
padding-inline-end: $-l;
}
.tri-layout-sides {
grid-column-start: a;
grid-column-end: a;
}
.tri-layout-sides-content {
display: block;
}
}
@include between($l, $xxl) {
.tri-layout-sides-content {
position: sticky;
top: 0;
max-height: 100vh;
min-height: 50vh;
overflow-y: scroll;
overflow-x: hidden;
height: 100%;
scrollbar-width: none;
-ms-overflow-style: none;
&::-webkit-scrollbar {
display: none;
}
}
}
@include larger-than($l) {
.tri-layout-mobile-tabs {
display: none;
}
.tri-layout-left-contents > *, .tri-layout-right-contents > * {
@include lightDark(opacity, 0.6, 0.75);
transition: opacity ease-in-out 120ms;
&:hover, &:focus-within {
opacity: 1 !important;
}
@media (prefers-contrast: more) {
opacity: 1 !important;
}
}
}
@include smaller-than($l) {
.tri-layout-container {
grid-template-areas: none;
grid-template-columns: 1fr;
grid-column-gap: 0;
padding-inline-end: $-xs;
padding-inline-start: $-xs;
.tri-layout-sides {
padding-inline-start: $-m;
padding-inline-end: $-m;
grid-column: 1/1;
}
.tri-layout-left > *, .tri-layout-right > * {
display: none;
pointer-events: none;
}
.tri-layout-left, .tri-layout-right {
padding-top: 0 !important;
}
.tri-layout-middle {
grid-area: none;
grid-row: 3;
grid-column: 1/1;
z-index: 1;
overflow: hidden;
transition: transform ease-in-out 240ms;
}
.tri-layout-left {
grid-row: 2;
}
&.show-info {
overflow: hidden;
.tri-layout-middle {
display: none;
}
.tri-layout-right > *, .tri-layout-left > * {
display: block;
pointer-events: auto;
}
}
}
}
@include smaller-than($m) {
.tri-layout-container {
margin-inline-start: 0;
margin-inline-end: 0;
}
}