css
centering responsive boxes columns vw & vh units full-width background colors accordions
centering
Vertical centering used to be pain but is much easier with flexbox or grid.
.flex-container {
display: flex;
justify-content: center;
align-items: center;
}
.grid-container {
display: flex;
place-items: center;
}
responsive boxes
These are also called aspect ratio boxes. The boxes can be used to produce responsive images and are particularly useful for content in iframes. There a number of ways to achieve aspect ratio boxes outlined on CSS Tricks.
columns
Columns are a quick way to split content up into evenly spaced columns. Issues can arise where the final item in a column get split between two columns. The following rules gets around that. Columns can also apportion child items in unexpected ways if the items are of unequal heights and their total number doesn’t divide evenly by the number of columns.
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
problems using vw and vh units
An issue with vw units is whether a browser calculates the scrollbar in its calculations which can throw off the display of edge-to-edge designs. This snippet sets a CSS variable on load and resize that can be used in lieu of vw and vh units to get around this issue.
window.addEventListener('load', function () {
let vw = document.documentElement.clientWidth / 100;
document.documentElement.style.setProperty('--vw', `${vw}px`);
let vh = document.documentElement.clientHeight / 100;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
window.addEventListener('resize', function() {
let vw = document.documentElement.clientWidth / 100;
document.documentElement.style.setProperty('--vw', `${vw}px`);
let vh = document.documentElement.clientHeight / 100;
document.documentElement.style.setProperty('--vh', `${vh}px`);
});
An issue with vh units has to do with how it is calculated on mobile screens. The browser toolbar that displays on load scrolls away on mobile. Unfortunately, this means the vh value changes as you begin to scroll which can cause values to get recalculated and sizing/positioning to change. A similar issue can occur if you have javascript logic that runs on the resize event. On mobile devices the resize event can get triggered simply by scrolling. It is better to check that the width is changing on resize before running any logic on resize. There are some new attributes to use in lieu of vh that seem to work more in line with expectations. svh
units will calculate the height to be the smallest value (i.e. on initial load before the OS bars scroll away) and maintain that value. Browser support isn’t perfect but you can use regular vh as a fallback.
.some-element {
height: 100vh;
height: 100svh;
}
full width background colors
The easiest way to get full width background colors without triggering horizontal scrollbars is to use border-image.
.full-width-background {
border-image: conic-gradient(backgroundColor 0 0) fill 0//0 100vw;
}
accordions
The easiest way to get accordions on a page is to use details and summary tags. These are ot very customizable though - see (https://dev.to/heyitsstacey/and-an-native-html-accordion-5797) for more info
<details>
<summary>accordion panel title</summary>
Accordion contents
</details>
Example details and summary tags
accordion panel title
Accordion contents- (https://codepen.io/DHawku/pen/vYzLNVK) has an example of how to animate grid-template-rows as a CSS alternative to jQuery slide methods
SCSS
responsive mixin bootstrap margins mixins functions
responsive mixin
// This would be fairly easy to accomplish using SCSS variables as well, though the
// media query itself would need to be written repeatedly, which this solution takes care of.
$grid-breakpoints: (
xs: 0,
sm: 600px,
md: 900px,
lg: 1200px,
xl: 1600px,
);
@mixin screen-mq($mq-breakpoint, $mq-breakpoints: $grid-breakpoints) {
// If $mq-breakpoint is a key that exists in $mq-breakpoints, get and use the value
@if map-has-key($mq-breakpoints, $mq-breakpoint) {
$mq-breakpoint: map-get($mq-breakpoints, $mq-breakpoint);
}
@media screen and (min-width: #{$mq-breakpoint}) {
@content;
}
}
bootstrap fake margin mixin
Bootstrap, Foundation and many other CSS frameworks use similar methods for grids. Typically there are three wrapper divs - div.container, div.row and div.column. The margins are determined by padding, margins and max-width values. Sometimes designs will require margins that match the grid container on only one side or only at certain screen widths. The hardcoded numerical values correspond to the container-max-width values.
%bootstrap-fake-margins {
padding-left: calc((100% - 840px) / 2);
padding-right: calc((100% - 840px) / 2);
margin-left: 15px;
margin-right: 15px;
// stylelint-disable-next-line at-rule-no-unknown
@include screen-mq(md) {
padding-left: calc((100% - 1000px) / 2);
padding-right: calc((100% - 1000px) / 2);
}
// stylelint-disable-next-line at-rule-no-unknown
@include screen-mq(lg) {
padding-left: calc((100% - 1140px) / 2);
padding-right: calc((100% - 1140px) / 2);
}
// stylelint-disable-next-line at-rule-no-unknown
@include screen-mq(xl) {
padding-left: calc((100% - 1400px) / 2);
padding-right: calc((100% - 1400px) / 2);
}
}
mixins
// Image Fluidity Include @access public
@mixin img-fluid {
max-width: 100%;
height: auto;
}
// List Style Stripper @access public
@mixin list-style-none {
list-style: none;
padding-left: 0;
}
functions
// rem-calc function to convert pixel values to rem values copied from Zurb Foundation.
// This relies on some other functions available in Foundation
@function rem-calc($values, $base-value: $rem-base) {
$max: length($values);
@if $max == 1 { @return convert-to-rem(nth($values, 1), $base-value); }
$remValues: ();
@for $i from 1 through $max {
$remValues: append($remValues, convert-to-rem(nth($values, $i), $base-value));
}
@return $remValues;
}
// A simpler example that assumes a 16px base font size.
// This only works if unitless numbers are passed in.
@function rem-calc($size) {
$remSize: $size / 16;
@return #{$remSize}rem;
}