ourbigbook.scss
// https://docs.ourbigbook.com#insane-link-parsing-rules#overview-of-files-in-this-repository
@use 'sass:math';
@use 'normalize.css/normalize.css';
@use 'katex/dist/katex.min.css';
@use 'tablesort/tablesort.css';
@import 'ourbigbook.common.scss';
@font-face { font-family: fa-brands-400; src: url(node_modules/@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2); }
@font-face { font-family: fa-regular-400; src: url(node_modules/@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2); }
@font-face { font-family: fa-solid-900; src: url(node_modules/@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2); }
$caption-margin-bottom: 7px;
$p-margin-vert: 14px;
$toplevel-horizontal-padding-mobile: 5px;
// Without this, hover on ToC makes ToC move around. Maybe we should scope to ToC only?
// TODO find proper way to do it without this random value.
$icon-font-size: .95em;
$sep-width: 1ch;
// Wraps "floating elements" such as images, so ensure they will not create a global scrollbar.
// Related issue: https://docs.ourbigbook.com/todo/vertical-scrollbar-when-image-title-contains-math-underscore
div.float-wrap {
display: inline-block;
overflow-x: auto;
width: 100%;
}
@mixin file-icon {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// up arrow https://fontawesome.com/v5/icons/file?f=classic&s=solid
content: "\f15b";
}
@mixin hidden {
display: none;
// The advantage of this is that when you hover, the height can increase a bit
// due to | separators which are very tall on certain fonts, and it is not very
// nice to see the page move.
//
// However, with visibility when the screen width is small, it always takes up a newline,
// to it is even less acceptable.
//
// So instead we fix the header height for now.
//
// https://github.com/ourbigbook/ourbigbook/issues/98
//visibility: hidden;
}
@mixin img-border {
border: 5px solid $color;
box-sizing: border-box;
}
@mixin link-icon {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// link https://fontawesome.com/v5/icons/link?f=classic&s=solid
content: "\f0c1";
}
@mixin multiline-caption {
border-left: 1px solid $color;
padding-left: 8px;
}
@mixin responsive-img {
@media only screen and (max-width: $max-mobile-width) {
height: auto;
width: 100%;
}
}
@mixin up-arrow-icon {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// up arrow https://fontawesome.com/v5/icons/arrow-up?f=classic&s=solid
content: "\f062";
}
@mixin visible {
display: inline;
//visibility: visible;
}
@mixin hide-hover {
position: absolute;
left: 0;
}
// CSS border triangles.
// https://css-tricks.com/snippets/css/css-triangle/
$toc-arrow-color: #009900;
$toc-arrow-width: 0.7em;
@mixin toc-arrow {
color: blue;
display: inline;
> * {
display: inline-block;
height: 0;
margin-right: 0.6 * $toc-arrow-width;
vertical-align: middle;
width: 0;
}
}
@mixin toc-hover-highlight-arrow {
@media only screen and (min-width: $max-mobile-width + 1) {
&:hover {
background-color: $target-background-color;
}
&:hover > * {
background-color: $target-background-color;
}
}
}
@mixin ourbigbook-title {
// Helps prevent the horizontal scrollbar on mobile.
word-wrap: break-word;
a {
&.split {
&::after {
content: " split";
}
&::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// adjust https://fontawesome.com/v5/icons/adjust?f=classic&s=solid
content: "\f042";
}
}
&.nosplit {
&::after {
content: " nosplit";
}
&::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// circle https://fontawesome.com/v5/icons/circle?f=classic&s=solid
content: "\f111";
}
}
&:visited {
color: $a-color-visited;
}
&.toc {
color: $a-color;
&::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// TOC_MARKER_SYMBOL
// list https://fontawesome.com/v5/icons/list?f=classic&s=solid
content: "\f03a";
}
}
}
span {
&.wcnt::before, &.wcntr::before {
font-family: "fa-regular-400";
font-weight: 400;
font-size: $icon-font-size;
// comment https://fontawesome.com/v5/icons/comment?f=classic&s=solid
content: "\f075";
}
&.dcnt::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// book https://fontawesome.com/v5/icons/book?f=classic&s=solid
content: "\f02d";
}
}
padding-left: 0;
.caption-prefix {
font-weight: bold;
}
.fa-regular-400, .fa-brands-400, .fa-solid-900 {
font-size: $icon-font-size;
}
.fa-regular-400 {
font-family: fa-regular-400;
}
.fa-brands-400 {
font-family: fa-brands-400;
}
.fa-solid-900 {
font-family: fa-solid-900;
}
// Hide by default, show if first child of hovered element.
.hide-hover {
@include hide-hover;
&:first-child {
@include hidden;
}
}
// We remove margins on narrow screens, so there's no space for the link.
@media only screen and (min-width: $max-mobile-width + 1) {
@media(hover: hover) and (pointer: fine) {
> :hover > .hide-hover:first-child {
@include visible;
}
}
}
// Highlight the element referred by the current hash
// so that the user can easily know which one it is.
:target {
background-color: $target-background-color;
}
blockquote {
border-left: 2px solid $color;
margin-left: 0;
margin-right: 0;
padding-left: 10px;
}
code {
background-color: $code-background-color;
}
// Paragraph.
// Can't be p because p can only contain phrasing it is insane:
// https://stackoverflow.com/questions/7168723/unordered-list-in-a-paragraph-element
div.p {
margin-bottom: $p-margin-vert;
margin-top: $p-margin-vert;
}
// Figures.
figure {
margin: $p-margin-vert 0;
&.multiline-caption {
@include multiline-caption;
}
figcaption {
margin-top: 5px;
}
}
div.h {
&:not(.top) {
// Top one has metadata which should be close below without margin.
margin-bottom: $p-margin-vert;
}
div.notnav {
@include h-common;
h1 {
@include h1-only;
}
h2, h3, h4, h5, h6 {
font-size: $header-font-size;
}
&:not(:last-child) {
margin-bottom: 10px;
}
}
.hover-meta {
@include hidden;
> :not(:last-child) {
margin-right: $sep-width;
}
margin-left: $sep-width;
}
@media only screen and (min-width: $max-mobile-width + 1) {
&:hover .hover-meta {
@include visible;
}
}
&.top {
div.notnav {
margin-bottom: 10px;
}
}
// Also show header metadata when the header is selected as the current #fragment.
&:target .hover-meta {
@include visible;
}
}
nav.h-nav {
margin-bottom: $p-margin-vert;
div.nav {
font-weight: bold;
margin-bottom: math.div($p-margin-vert, 2);
&:before {
// Downwards Arrow with Tip Rightwards: https://www.compart.com/en/unicode/U+21B3
content: "\21b3";
padding-right: 0.5ch;
}
img.logo {
height: 1em;
}
> :not(:last-child) {
margin-right: $sep-width
}
&.file {
> :first-child::before {
@include file-icon;
}
}
&.ancestors {
// First ancestors.
> :first-child::before {
@include up-arrow-icon;
}
// Other ancestors.
> :not(:first-child)::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// right arrow https://fontawesome.com/v5/icons/arrow-right?f=classic&s=solid
content: "\f061";
}
}
}
a {
// u for Up
&.u::before {
@include up-arrow-icon;
}
&.wiki {
&::before {
font-family: "fa-brands-400";
font-weight: bold;
font-size: $icon-font-size;
// Wikipedia w https://fontawesome.com/v5/icons/wikipedia-w?f=brands&s=solid
content: "\f266";
}
&::after {
content: " wiki"
}
}
}
span.tags::before {
font-family: "fa-solid-900";
font-weight: 900;
font-size: $icon-font-size;
// tags https://fontawesome.com/v5/icons/tags?f=classic&s=solid
content: "\f02c";
}
.toc::after {
content: " toc";
}
}
// https://docs.ourbigbook.com#background-color-of-transparent-images
img {
background-color: white;
@include responsive-img;
&.border {
@include img-border;
}
}
nav {
img {
// Undo responsive-img width ==100 for navigation images, otherwise
// the OurBigBook.com iamge becomes huge and breaks the navigation.
width: auto;
}
}
iframe {
@include responsive-img;
box-sizing: border-box;
&.border {
@include img-border;
}
}
// Math.
// https://stackoverflow.com/questions/50896041/katex-font-size/57355836#57355836
.katex { font-size: 1.5em; }
.math {
align-items: center;
overflow-x: auto;
overflow-y: clip;
margin-bottom: $p-margin-vert;
margin-top: $p-margin-vert;
.caption {
margin-top: $caption-margin-bottom;
}
.equation {
align-items: center;
display: flex;
> :nth-child(1) {
flex-grow: 9;
}
> :nth-child(2) {
flex-grow: 1;
text-align: right;
}
}
div.number {
margin-left: 1.5em;
}
}
.metrics > :not(:first-child) {
margin-left: 0.5em;
}
pre {
@include pre;
}
div.multiline-caption {
@include multiline-caption;
}
// Tables
.table {
margin: $p-margin-vert 0;
overflow-x: auto;
&.multiline-caption {
@include multiline-caption;
}
table {
$table_border: 1px solid $color;
border: $table_border;
border-collapse: collapse;
margin: math.div($p-margin-vert, 2) 0;
th, td {
border: $table_border;
padding: 5px 5px;
}
}
.caption {
margin-bottom: $caption-margin-bottom;
}
}
ol, ul {
padding-left: 30px;
li {
// https://github.com/ourbigbook/ourbigbook/issues/68
margin-bottom: $p-margin-vert;
margin-top: $p-margin-vert;
}
}
// Shows on ToC and on metadata at the end like the ancestor list.
.metrics {
color: $color-discreet;
}
// Table of contents.
.toc-container {
margin-bottom: $p-margin-vert;
overflow-x: auto;
// On mobile, this would make:
// - prevent squishing of very to the right elements which:
// - makes them more readable
// - prevents large useless vertical displacement
// But it also makes the very first elements of small tocs
// require horizontal scroll so it doesn't feel like it's worth it :-(
// What we want is to check is: is the element's absolute position more than 80%
// to the right of the screen? Then we should just nowrap.
//white-space: nowrap;
// Don't wrap lines after level 5 on mobile.
// Very deep toc items just take up vertical space and are completely unreadable.
// Work around that on mobile by not wrapping lines after a certain level.
// Users can still read by horizontal scrolling if they really want to.
@media only screen and (max-width: $max-mobile-width) {
li { li { li { li { li { li { li {
white-space: nowrap;
} } } } } } }
}
ul {
list-style-type: none;
li {
// https://github.com/ourbigbook/ourbigbook/issues/68
$toc-sep: 0.3em;
margin-bottom: $toc-sep;
margin-top: $toc-sep;
@media only screen and (min-width: $max-mobile-width + 1) {
div:hover span.not-arrow span.hover-metadata {
@include visible;
}
}
div:target span.not-arrow span.hover-metadata {
@include visible;
}
// Current
.c::before {
@include link-icon;
}
.c::after {
content: " link";
}
// Up
.u::before {
@include up-arrow-icon;
}
div {
display: flex;
span.not-arrow {
span.hover-metadata {
@include hidden;
> a {
margin-left: $sep-width;
}
}
}
// Take up space on LIs that don't have an arrow.
&.arrow {
@include toc-arrow;
& > * {
border-left: $toc-arrow-width solid transparent;
border-right: $toc-arrow-width solid transparent;
border-top: $toc-arrow-width solid transparent;
}
}
}
// Right arrow for open LIs.
&.has-child > div > div.arrow {
@include toc-arrow;
@include toc-hover-highlight-arrow;
& > * {
border-left: $toc-arrow-width solid transparent;
border-right: $toc-arrow-width solid transparent;
border-top: $toc-arrow-width solid $toc-arrow-color;
}
}
&.close {
ul {
display: none;
}
// Down arrow for closed LIs.
&.has-child > div > div.arrow {
@include toc-arrow;
@include toc-hover-highlight-arrow;
& > * {
border-top: $toc-arrow-width solid transparent;
border-bottom: $toc-arrow-width solid transparent;
border-left: $toc-arrow-width solid $toc-arrow-color;
}
}
}
}
}
> ul {
padding-left: 0px;
margin-top: 0;
margin-bottom: 0;
> li > ul {
padding-left: 0px;
* {
// Ignore special background on code blocks.
// TODO this was enabled at one point not sure why, seems to be at
// f8fc9eacfa794b95c1d9982a04b62603e6d0bb83
//background-color: $background-color;
}
}
}
.title {
font-size: $header-font-size;
font-weight: bold;
}
.metrics {
padding-left: $sep-width;
}
@media only screen and (max-width: $max-mobile-width) {
.metrics {
display: none;
}
}
// Override the default URL fragment behaviour, only color the toc title when the ToC
// is targeted, otherwise it is too annoying. Especially because the first thing
// you want to do on a ToC is to click that nice big link. And then the entire ToC becomes
// red and unreadable (especially due to link colors) and then it requires some thinking to how
// to make it stop being red (remove #fragment from URL manually or find another ID on page).
// So we just take the solution that prevents the user from shooting themselves.
background-color: $background-color;
div:target {
background-color: $target-background-color;
}
div:target * {
background-color: $target-background-color;
}
&:target div.title-div {
background-color: $target-background-color;
}
}
span.sep {
display: inline-block;
width: $sep-width;
}
sup.ref {
// https://stackoverflow.com/questions/6900124/how-to-make-certain-text-not-selectable-with-css
user-select: none;
}
// Overrides for the tablesort.css
// https://raw.githubusercontent.com/tristen/tablesort/5.2.1/tablesort.css
th[role=columnheader]:not(.no-sort):after {
border-color: $color transparent;
}
video {
@include responsive-img;
&.border {
@include img-border;
}
}
}
.ourbigbook {
@include body;
@include ourbigbook-title;
// Produces the margin on all toplevel elements.
// The on-hover links will show up in that margin.
> * {
@media only screen and (max-width: $max-mobile-width) {
padding-left: $toplevel-horizontal-padding-mobile;
padding-right: $toplevel-horizontal-padding-mobile;
}
@media only screen and (min-width: $max-mobile-width + 1) {
padding-left: $toplevel-horizontal-padding-left;
padding-right: $toplevel-horizontal-padding-right;
}
// For on-hover links.
// https://stackoverflow.com/questions/10487292/position-absolute-but-relative-to-parent
position: relative;
}
}
a.selflink::before {
@include link-icon;
font-size: $font-size;
position: absolute;
left: -0.1em;
}
// A subset of .ourbigbook used for titles-only renders as appear or article lists on OurBigBook Web.
.ourbigbook-title {
@include ourbigbook-title;
}