/// ===== Root ===== /// Every HTML document using Bluelib must define a root, an element where all bluelib styles can start being applied. /// Elements outside the root won't be styled at all, allowing Bluelib's styling to be contained in components or modules of a website. @{bluelib} { // Set the background defined in the palette background-color: @hex-background; // Set the base color to the foreground defined in the palette .bluelib-color(@hex-foreground); // By default, text should use the main font .font-text(); /// ===== All ===== /// By default, browsers style elements with some weird rules. /// This is an attempt to correct them, and to implement some Bluelib magic. &, @{all} { // Globally set the box-sizing to border-box, as content-box is completely insane &, &::before, &::after { box-sizing: border-box; } // Bluelib magic! // This rule sets the color of all text to be equal to the current .bluelib-color() at 100% opacity. // Thanks, CSS variables! color: @bA; } /// ===== Layouts ===== /// Layouts arrange the content displayed inside the root. /// Layouts are the second element in the Bluelib hierarchy, immediately following the root. /// Ideally, a single layout should be used per page. // The base layout class. @{layout} { display: grid; justify-content: stretch; align-items: stretch; width: 100%; } // A layout with a single container spanning the whole screen. @{layout-fill} { padding: 4px; grid-template-areas: "single"; grid-template-columns: 1fr; grid-template-rows: 1fr; } @{layout-fill-single} { grid-area: single; } // A layout with a centered 1024px wide main container and two symmetric containers at the sides. @{layout-threecol} { padding: 4px; @media screen and (min-width: 1281px) { grid-template-areas: "left center right"; grid-template-columns: 1fr auto 1fr; grid-template-rows: 1fr; } // If the side containers would be smaller than 128px (if the screen is narrower than 1280px), the smaller containers are moved below the main one. @media screen and (max-width: 1280px) { grid-template-areas: "center center" "left right"; grid-template-columns: 1fr 1fr; grid-template-rows: auto auto; // Keep the container limited to 1024px and centered max-width: 1024px; margin-left: auto; margin-right: auto; } } @{layout-threecol-left} { grid-area: left; @media screen and (min-width: 1281px) { justify-self: end; } @media screen and (max-width: 1280px) { justify-self: stretch; } } @{layout-threecol-center} { grid-area: center; // Ensure the container doesn't eat up all the space max-width: 1024px; } @{layout-threecol-right} { grid-area: right; @media screen and (min-width: 1281px) { justify-self: start; } @media screen and (max-width: 1280px) { justify-self: stretch; } } /// ===== Panels ===== /// Panels are the main sectioning elements available in Bluelib. /// Many instance of them should be present on the page! /// They should group small amounts of tightly related content, which can be understood more or less separately from the rest of the page. // The base panel class. @{panel} { // Panels have a margin to separate them from other elements margin: 8px 0; // And a padding to separate them from their contents padding: 8px; // Panels should try to fill the most space possible width: 100%; background-color: @b0; border-color: @b1; // The first and last elements of a panel should not have a margin > @{all} { &:first-child { margin-top: 0; } &:last-child { margin-bottom: 0; } } } // A panel which encloses its contents with a border. @{panel-box} { border-radius: 4px; border-width: 2px; border-style: solid; } // A panel which encloses its contents with a quote-like border. @{panel-blockquote} { border-radius: 4px; border-width: 0 0 0 2px; border-style: solid; } // A panel with no border whose contents are made smaller. @{panel-aside} { border-width: 0; font-size: smaller; } /// ===== Split ===== /// A split is an element which splits everything contained inside in multiple columns of equal width. @{split} { display: flex; flex-wrap: wrap; gap: 4px 8px; justify-content: center; > @{panel} { // Add a horizontal margin to panels margin: 0; } // Allow contained elements to grow > @{all} { flex-grow: 1; flex-shrink: 0; flex-basis: 0; } } // Force a split to wrap @{split-forcewrap} { flex-grow: 0; flex-shrink: 0; flex-basis: 100%; } // --- Images --- @{image} { display: block; max-width: 100%; margin-left: auto; margin-right: auto; object-fit: contain; } @{image-free} { max-width: unset; max-height: unset; } @{image-limited} { max-height: max(37.5vw, 66.6vh); } // --- Forms --- @{form} { display: grid; align-items: center; row-gap: 4px; column-gap: 8px; grid-template-columns: minmax(auto, 1fr) 5fr; } @{form-label} { grid-column: 1; justify-self: end; } @{form-input} { grid-column: 2; justify-self: stretch; width: 100%; } @{form-submit} { width: auto; } @{form-buttons} { grid-column-start: 1; grid-column-end: 3; display: flex; gap: 8px; justify-content: center; align-items: center; width: 100%; margin-top: 8px; margin-bottom: 8px; &:first-child { margin-top: 0; } &:last-child { margin-bottom: 0; } } // --- Buttons --- @{button} { display: inline-flex; justify-content: center; align-items: center; background-color: @bA; border: none; color: @hex-btn-text; padding: 6px 16px; border-radius: 4px; font-family: inherit; font-size: inherit; cursor: pointer; &:hover { background-color: @bC; } &:focus-visible { outline: 4px solid @b7 !important; } &:active { background-color: @bF; } &@{status-disabled} { &:hover { background-color: @bA; } &:active { background-color: @bA; } } } @{button-fill-width} { width: 100%; } @{button-toggle} { padding: 4px 14px; border-width: 2px; border-style: solid; &@{status-disabled} { border-style: dashed; } } @{button-toggle-off} { border-color: @bA; color: @bA; background-color: @b0; &:hover { border-color: @bC; color: @bC; background-color: @b1; } &:active { border-color: @bF; color: @bF; background-color: @b2; } &@{status-disabled} { border-style: dashed; &:hover { border-color: @bA; color: @bA; background-color: @b0; } &:active { border-color: @bA; color: @bA; background-color: @b0; } } } @{button-toggle-on} { border-color: @bF; color: @bF; background-color: @b2; &:hover { border-color: @bC; color: @bC; background-color: @b1; } &:active { border-color: @bA; color: @bA; background-color: @b0; } &@{status-disabled} { border-style: dashed; &:hover { border-color: @bF; color: @bF; background-color: @b2; } &:active { border-color: @bF; color: @bF; background-color: @b2; } } } // --- Inputs --- @{input} { border-style: solid; border-color: @b3; color: @bA; background-color: @b0; font-family: inherit; font-size: inherit; &::placeholder { color: @b4; opacity: 1; } &:optional, &:optional::placeholder { font-style: italic; } // &:valid:not(:placeholder-shown) { // .bluelib-color(@hex-lime); // } &:invalid:not(:placeholder-shown) { .bluelib-color(@hex-red); } &:hover, &:focus { border-color: @b6; color: @bF; background-color: @b1; &::placeholder { color: @b7; } } &@{status-disabled} { border-style: dashed; &:hover, &:focus { border-color: @b3; color: @bA; background-color: @b0; &::placeholder { color: @b4; } } } } @{input-field} { cursor: text; border-width: 0 0 2px 0; border-radius: 4px 4px 0 0; padding: 4px 6px; } @{input-select}, @{input-multiselect} { // Browsers add 4px of unremovable horizontal padding to options for some reason padding: 4px 2px; } @{input-select-option}, @{input-multiselect-option} { font-weight: normal; color: @bA; padding: 4px 4px; // TODO: style checked elements, when it will be possible } @{input-select-optgroup}, @{input-multiselect-optgroup} { font-weight: bold; color: @hex-accent; padding: 4px 4px; @{input-select-option}, @{input-multiselect-option} { padding: 4px 20px; &::before { content: ""; } } } @{input-select-optgroup}, @{input-select-option}, @{input-multiselect-optgroup}, @{input-multiselect-option} { font-family: inherit; font-size: inherit; font-style: inherit; } @{input-select} { cursor: context-menu; border-width: 0 0 2px 0; border-radius: 4px 4px 0 0; @media screen and (-webkit-min-device-pixel-ratio:0) { @{input-select-option}, @{input-select-optgroup} { background-color: @hex-background; } } } @{input-multiselect} { cursor: vertical-text; border-width: 0 0 0 2px; border-radius: 0 4px 4px 0; } // --- Element status --- @{status-hoverable} { cursor: help; } @{status-clickable} { cursor: pointer; } @{status-disabled} { cursor: not-allowed !important; opacity: 50%; } // --- Elements --- @{element-title} { text-align: center; .bluelib-color(@hex-accent); .font-title(); } @{element-paragraph} { } @{element-separator} { border-width: 1px; border-style: solid; border-color: @b1; } @{element-list-item} { margin: 10px 0; } @{element-anchor} { .bluelib-color(@hex-link); text-decoration-line: underline; text-decoration-style: solid; text-decoration-color: currentColor; text-decoration-thickness: 1px; &:hover, &:focus { .bluelib-color(@hex-link-hover); } &:focus-visible { text-decoration-thickness: 2px; } &:active { .bluelib-color(@hex-link-active); } &@{status-disabled} { text-decoration-style: dashed; &:hover, &:focus { .bluelib-color(@hex-link); } &:active { .bluelib-color(@hex-link); } } } // --- Alignment --- @{align-left} { text-align: left; } @{align-center} { text-align: center; } @{align-right} { text-align: right; } // --- Sizes --- @{size-xxl} { font-size: xx-large; } @{size-xl} { font-size: x-large; } @{size-l} { font-size: large; } @{size-m} { font-size: medium; } @{size-s} { font-size: small; } @{size-xs} { font-size: x-small; } @{size-xxs} { font-size: xx-small; } // --- Styles --- @{style-bold} { font-weight: bold; .bluelib-color(@hex-accent); } @{style-italic} { font-style: italic; } @{style-underline} { text-decoration-line: underline; } @{style-strike} { text-decoration-line: line-through; } @{style-monospace} { .font-code(); } @{style-keyboard} { .font-code(); padding: 2px 4px; border: 2px outset; border-radius: 4px; } // --- Colors --- @{color-red} { .bluelib-color(@hex-red) } @{color-orange} { .bluelib-color(@hex-orange) } @{color-yellow} { .bluelib-color(@hex-yellow) } @{color-lime} { .bluelib-color(@hex-lime) } @{color-cyan} { .bluelib-color(@hex-cyan) } @{color-blue} { .bluelib-color(@hex-blue) } @{color-magenta} { .bluelib-color(@hex-magenta) } @{color-gray} { .bluelib-color(@hex-gray) } }