]> BookStack Code Mirror - bookstack/blob - resources/sass/_layout.scss
Layout: Added scroll fade to the sidebars
[bookstack] / resources / sass / _layout.scss
1 @use "mixins";
2 @use "vars";
3
4
5 /**
6  * Generic content container
7  */
8 .container {
9   max-width: vars.$bp-xxl;
10   margin-inline-start: auto;
11   margin-inline-end: auto;
12   padding-inline-start: vars.$m;
13   padding-inline-end: vars.$m;
14   &.medium {
15     max-width: 1100px;
16   }
17   &.small {
18     max-width: 840px;
19   }
20   &.very-small {
21     max-width: 480px;
22   }
23 }
24
25 /**
26  * Core grid layout system
27  */
28 .grid {
29   display: grid;
30   grid-column-gap: vars.$l;
31   grid-row-gap: vars.$l;
32   > * {
33     min-width: 0;
34   }
35   &.half {
36     grid-template-columns: 1fr 1fr;
37   }
38   &.third {
39     grid-template-columns: 1fr 1fr 1fr;
40   }
41   &.left-focus {
42     grid-template-columns: 2fr 1fr;
43   }
44   &.right-focus {
45     grid-template-columns: 1fr 3fr;
46   }
47   &.gap-y-xs {
48     grid-row-gap: vars.$xs;
49   }
50   &.gap-xl {
51     grid-column-gap: vars.$xl;
52     grid-row-gap: vars.$xl;
53   }
54   &.gap-xxl {
55     grid-column-gap: vars.$xxl;
56     grid-row-gap: vars.$xxl;
57   }
58   &.v-center {
59     align-items: center;
60   }
61   &.v-end {
62     align-items: end;
63   }
64   &.no-gap {
65     grid-row-gap: 0;
66     grid-column-gap: 0;
67   }
68   &.no-row-gap {
69     grid-row-gap: 0;
70   }
71 }
72
73 @include mixins.smaller-than(vars.$bp-m) {
74   .grid.third:not(.no-break) {
75     grid-template-columns: 1fr 1fr;
76   }
77   .grid.half:not(.no-break), .grid.left-focus:not(.no-break), .grid.right-focus:not(.no-break) {
78     grid-template-columns: 1fr;
79   }
80   .grid.half.collapse-xs {
81     grid-template-columns: 1fr 1fr;
82   }
83   .grid.gap-xl {
84     grid-column-gap: vars.$m;
85     grid-row-gap: vars.$m;
86   }
87   .grid.right-focus.reverse-collapse > *:nth-child(2) {
88     order: 0;
89   }
90   .grid.right-focus.reverse-collapse > *:nth-child(1) {
91     order: 1;
92   }
93 }
94
95 @include mixins.smaller-than(vars.$bp-s) {
96   .grid.third:not(.no-break) {
97     grid-template-columns: 1fr;
98   }
99 }
100
101 @include mixins.smaller-than(vars.$bp-xs) {
102   .grid.half.collapse-xs {
103     grid-template-columns: 1fr;
104   }
105 }
106
107 #content {
108   flex: 1 0 auto;
109 }
110
111 /**
112  * Flexbox layout system
113  */
114 body.flexbox {
115   display: flex;
116   flex-direction: column;
117   align-items: stretch;
118   height: 100%;
119   min-height: 100%;
120   max-height: 100%;
121   overflow: hidden;
122   #content {
123     flex: 1;
124     display: flex;
125     min-height: 0;
126   }
127 }
128
129 .flex-fill {
130   display: flex;
131   align-items: stretch;
132   min-height: 0;
133   max-width: 100%;
134   position: relative;
135 }
136
137 .flex-container-row {
138   display: flex;
139   flex-direction: row;
140   &.v-center {
141     align-items: center;
142   }
143 }
144
145 .flex-container-column {
146   display: flex;
147   flex-direction: column;
148 }
149
150 .flex-container-row.inline, .flex-container-column.inline {
151   display: inline-flex !important;
152 }
153
154 .flex-container-column.wrap, .flex-container-row.wrap {
155   flex-wrap: wrap;
156 }
157
158 .flex {
159   min-height: 0;
160   flex: 1;
161   max-width: 100%;
162   &.fit-content {
163     flex-basis: auto;
164     flex-grow: 0;
165   }
166   &.fill-area {
167     flex-grow: 1;
168     flex-shrink: 0;
169     min-width: fit-content;
170   }
171 }
172
173 .flex-2 {
174   min-height: 0;
175   flex: 2;
176   max-width: 100%;
177 }
178
179 .flex-3 {
180   min-height: 0;
181   flex: 3;
182   max-width: 100%;
183 }
184
185 .flex-none {
186   flex: none;
187 }
188
189 .justify-flex-start {
190   justify-content: flex-start;
191 }
192 .justify-flex-end {
193   justify-content: flex-end;
194 }
195 .justify-center {
196   justify-content: center;
197 }
198 .justify-space-between {
199   justify-content: space-between;
200 }
201 .items-center {
202   align-items: center;
203 }
204 .items-stretch {
205   align-items: stretch;
206 }
207
208 /**
209  * Min width utilities
210  */
211 .min-width-xxxxs {
212   min-width: 60px;
213 }
214 .min-width-xxxs {
215   min-width: 80px;
216 }
217 .min-width-xxs {
218   min-width: 100px;
219 }
220 .min-width-xs {
221   min-width: 120px;
222 }
223 .min-width-s {
224   min-width: 160px;
225 }
226 .min-width-m {
227   min-width: 200px;
228 }
229 .min-width-l {
230   min-width: 240px;
231 }
232 .min-width-xl {
233   min-width: 280px;
234 }
235 .min-width-xxl {
236   min-width: 320px;
237 }
238
239 /**
240  * Display and float utilities
241  */
242 .block {
243   display: block !important;
244   position: relative;
245 }
246
247 .inline {
248   display: inline !important;
249 }
250
251 .block.inline {
252   display: inline-block !important;
253 }
254
255 .relative {
256   position: relative;
257 }
258
259 .fixed {
260   position: fixed;
261   z-index: 20;
262   &.top-right {
263     top: 0;
264     right: 0;
265   }
266 }
267
268 .hidden {
269   display: none !important;
270 }
271
272 .overflow-hidden {
273   overflow: hidden;
274 }
275
276 .height-fill {
277   height: 100%;
278 }
279
280 .height-auto {
281   height: auto !important;
282 }
283
284 .float {
285   float: left;
286   &.right {
287     float: right;
288   }
289 }
290
291 .sticky-top-m {
292   position: sticky;
293   top: vars.$m;
294 }
295
296 /**
297  * Visibility
298  */
299 @each $sizeLetter, $size in vars.$screen-sizes {
300   @include mixins.smaller-than($size) {
301     .hide-under-#{$sizeLetter} {
302       display: none !important;
303     }
304   }
305   @include mixins.larger-than($size) {
306     .hide-over-#{$sizeLetter} {
307       display: none !important;
308     }
309   }
310 }
311
312 [hidden] {
313   display: none !important;
314 }
315
316 .screen-reader-only {
317   position: absolute;
318   inset-inline-start: -10000px;
319   top: auto;
320   width: 1px;
321   height: 1px;
322   overflow: hidden;
323 }
324
325 /**
326  * Border radiuses
327  */
328 .rounded {
329   border-radius: 4px;
330 }
331
332 /**
333  * Inline content columns
334  */
335 .dual-column-content {
336   columns: 2;
337 }
338
339 @include mixins.smaller-than(vars.$bp-m) {
340   .dual-column-content {
341     columns: 1;
342   }
343 }
344
345
346 /**
347  * Fixes
348  */
349 .clearfix::before,
350 .clearfix::after {
351   content: " ";
352   display: table;
353 }
354 .clearfix::after {
355   clear: both;
356 }
357
358 /**
359  * View Layouts
360  */
361 .tri-layout-container {
362   display: grid;
363   margin-inline-start: vars.$xl;
364   margin-inline-end: vars.$xl;
365   grid-template-columns: 1fr 4fr 1fr;
366   grid-template-areas: "a b c";
367   grid-column-gap: vars.$xl;
368   position: relative;
369 }
370 .tri-layout-sides {
371   grid-column-start: a;
372   grid-column-end: c;
373   grid-row: 1;
374   min-width: 0;
375   z-index: 4;
376 }
377 .tri-layout-sides-content {
378   display: grid;
379   grid-template-areas: "a b c";
380   grid-template-columns: 1fr 4fr 1fr;
381   height: 100%;
382 }
383 .tri-layout-middle {
384   grid-area: b;
385   padding-top: vars.$m;
386   min-width: 0;
387   z-index: 5;
388 }
389 .tri-layout-right {
390   grid-area: c;
391   min-width: 0;
392   position: relative;
393 }
394 .tri-layout-left {
395   grid-area: a;
396   min-width: 0;
397   position: relative;
398 }
399
400 @include mixins.larger-than(vars.$bp-xxl) {
401   .tri-layout-left-contents, .tri-layout-right-contents {
402     padding: vars.$xl vars.$m;
403     position: sticky;
404     top: 0;
405     max-height: 100vh;
406     min-height: 50vh;
407     overflow-y: scroll;
408     overflow-x: hidden;
409     height: 100%;
410     scrollbar-width: none;
411     -ms-overflow-style: none;
412     &::-webkit-scrollbar {
413       display: none;
414     }
415   }
416   .tri-layout-middle-contents {
417     max-width: 940px;
418     margin: 0 auto;
419   }
420 }
421 @include mixins.between(vars.$bp-xxl, vars.$bp-xxxl) {
422   .tri-layout-sides-content, .tri-layout-container {
423     grid-template-columns: 1fr calc(940px + (2 * vars.$m)) 1fr;
424   }
425   .tri-layout-container {
426     grid-column-gap: vars.$s;
427     margin-inline-start: vars.$m;
428     margin-inline-end: vars.$m;
429   }
430 }
431 @include mixins.smaller-than(vars.$bp-xxl) {
432   .tri-layout-container {
433     grid-template-areas:  "a b b";
434     grid-template-columns: 1fr 3fr;
435     grid-template-rows: min-content min-content 1fr;
436     margin-inline-start: (vars.$m + vars.$xxs);
437     margin-inline-end: (vars.$m + vars.$xxs);
438   }
439   .tri-layout-sides {
440     grid-column-start: a;
441     grid-column-end: a;
442   }
443   .tri-layout-sides-content {
444     display: block;
445   }
446 }
447 @include mixins.between(vars.$bp-l, vars.$bp-xxl) {
448   .tri-layout-sides-content {
449     position: sticky;
450     top: 0;
451     max-height: 100vh;
452     min-height: 50vh;
453     overflow-y: scroll;
454     overflow-x: hidden;
455     height: 100%;
456     scrollbar-width: none;
457     -ms-overflow-style: none;
458     padding-inline: vars.$m;
459     margin-inline: -(vars.$m);
460     &::-webkit-scrollbar {
461       display: none;
462     }
463   }
464 }
465 @include mixins.larger-than(vars.$bp-l) {
466   .tri-layout-mobile-tabs {
467     display: none;
468   }
469   .tri-layout-left-contents > *, .tri-layout-right-contents > * {
470     @include mixins.lightDark(opacity, 0.6, 0.75);
471     transition: opacity ease-in-out 120ms;
472     &:hover, &:focus-within {
473       opacity: 1 !important;
474     }
475     @media (prefers-contrast: more) {
476       opacity: 1 !important;
477     }
478   }
479 }
480 @include mixins.smaller-than(vars.$bp-l) {
481   .tri-layout-container {
482     grid-template-areas:  none;
483     grid-template-columns: 1fr;
484     grid-column-gap: 0;
485     padding-inline-end: vars.$xs;
486     padding-inline-start: vars.$xs;
487     .tri-layout-sides {
488       padding-inline-start: vars.$m;
489       padding-inline-end: vars.$m;
490       grid-column: 1/1;
491     }
492     .tri-layout-left > *, .tri-layout-right > * {
493       display: none;
494       pointer-events: none;
495     }
496     .tri-layout-left, .tri-layout-right {
497       padding-top: 0 !important;
498     }
499     .tri-layout-middle {
500       grid-area: none;
501       grid-row: 3;
502       grid-column: 1/1;
503       z-index: 1;
504       overflow: hidden;
505       transition: transform ease-in-out 240ms;
506     }
507     .tri-layout-left {
508       grid-row: 2;
509     }
510     &.show-info {
511       overflow: hidden;
512       .tri-layout-middle {
513         display: none;
514       }
515       .tri-layout-right  > *, .tri-layout-left > * {
516         display: block;
517         pointer-events: auto;
518       }
519     }
520   }
521 }
522
523 @include mixins.smaller-than(vars.$bp-m) {
524   .tri-layout-container {
525     margin-inline-start: 0;
526     margin-inline-end: 0;
527   }
528 }
529
530 /**
531  * Scroll Indicators
532  */
533 .scroll-away-from-top:before,
534 .scroll-away-from-bottom:after {
535   content: '';
536   display: block;
537   position: absolute;
538   @include mixins.lightDark(color, #F2F2F2, #111);
539   left: 0;
540   top: 0;
541   width: 100%;
542   height: 50px;
543   background: linear-gradient(to bottom, currentColor, transparent);
544   z-index: 2;
545 }
546 .scroll-away-from-bottom:after {
547   top: auto;
548   bottom: 0;
549   background: linear-gradient(to top, currentColor, transparent);
550 }