# 30 Seconds of CSS

[](https://github.com/30-seconds/30-seconds-of-css/blob/master/LICENSE) [](http://makeapullrequest.com) [](https://insight.io/github.com/30-seconds/30-seconds-of-css/tree/master/?source=0)
A curated collection of useful CSS snippets you can understand in 30 seconds or less.
Inspired by [30 seconds of code](https://github.com/30-seconds/30-seconds-of-code).
## View online
https://css.30secondsofcode.org
## Contributing
See CONTRIBUTING.md for the snippet template.
#### Related projects
- [30 Seconds of Code](https://30secondsofcode.org/)
- [30 Seconds of Interviews](https://30secondsofinterviews.org/)
- [30 Seconds of React](https://github.com/30-seconds/30-seconds-of-react)
### Animation
View contents
* [`Bouncing loader`](#bouncing-loader)
* [`Button border animation`](#button-border-animation)
* [`Donut spinner`](#donut-spinner)
* [`Easing variables`](#easing-variables)
* [`Height transition`](#height-transition)
* [`Hover shadow box animation`](#hover-shadow-box-animation)
* [`Hover underline animation`](#hover-underline-animation)
* [`Pulse loader`](#pulse-loader)
### Interactivity
View contents
* [`Disable selection`](#disable-selection)
* [`Hamburguer Button`](#hamburguer-button)
* [`Popout menu`](#popout-menu)
* [`Sibling fade`](#sibling-fade)
### Layout
View contents
* [`Box-sizing reset`](#box-sizing-reset)
* [`Clearfix`](#clearfix)
* [`Constant width to height ratio`](#constant-width-to-height-ratio)
* [`Display table centering`](#display-table-centering)
* [`Evenly distributed children`](#evenly-distributed-children)
* [`Fit image in container`](#fit-image-in-container)
* [`Flexbox centering`](#flexbox-centering)
* [`Ghost trick`](#ghost-trick)
* [`Grid centering`](#grid-centering)
* [`Last item with remaining available height`](#last-item-with-remaining-available-height)
* [`Lobotomized Owl Selector`](#lobotomized-owl-selector)
* [`Offscreen`](#offscreen)
* [`3-tile layout`](#3-tile-layout)
* [`Transform centering`](#transform-centering)
* [`Truncate text multiline`](#truncate-text-multiline)
* [`Truncate text`](#truncate-text)
### Other
View contents
* [`Calc()`](#calc)
* [`Custom variables`](#custom-variables)
### Visual
View contents
* [`Border with top triangle`](#border-with-top-triangle)
* [`Circle`](#circle)
* [`Counter`](#counter)
* [`Custom scrollbar`](#custom-scrollbar)
* [`Custom text selection`](#custom-text-selection)
* [`Drop cap`](#drop-cap)
* [`Dynamic shadow`](#dynamic-shadow)
* [`Etched text`](#etched-text)
* [`Focus Within`](#focus-within)
* [`Fullscreen`](#fullscreen)
* [`Gradient text`](#gradient-text)
* [`Hairline border`](#hairline-border)
* [`Mouse cursor gradient tracking`](#mouse-cursor-gradient-tracking)
* [`Navigation list item hover and focus effect`](#navigation-list-item-hover-and-focus-effect)
* [`:not selector`](#not-selector)
* [`Overflow scroll gradient`](#overflow-scroll-gradient)
* [`Pretty text underline`](#pretty-text-underline)
* [`Reset all styles`](#reset-all-styles)
* [`Shape separator`](#shape-separator)
* [`System font stack`](#system-font-stack)
* [`Toggle switch`](#toggle-switch)
* [`Transform - Detransform`](#transform---detransform)
* [`Triangle`](#triangle)
* [`Zebra striped list`](#zebra-striped-list)
---
## Animation
### Bouncing loader
Creates a bouncing loader animation.
```html
```
```css
@keyframes bouncing-loader {
to {
opacity: 0.1;
transform: translate3d(0, -1rem, 0);
}
}
.bouncing-loader {
display: flex;
justify-content: center;
}
.bouncing-loader > div {
width: 1rem;
height: 1rem;
margin: 3rem 0.2rem;
background: #8385aa;
border-radius: 50%;
animation: bouncing-loader 0.6s infinite alternate;
}
.bouncing-loader > div:nth-child(2) {
animation-delay: 0.2s;
}
.bouncing-loader > div:nth-child(3) {
animation-delay: 0.4s;
}
```
#### Explanation
Note: `1rem` is usually `16px`.
1. `@keyframes` defines an animation that has two states, where the element changes `opacity` and is translated up on the 2D plane using `transform: translate3d()`. Using a single axis translation on `transform: translate3d()` improves the performance of the animation.
2. `.bouncing-loader` is the parent container of the bouncing circles and uses `display: flex` and `justify-content: center` to position them in the center.
3. `.bouncing-loader > div`, targets the three child `div`s of the parent to be styled. The `div`s are given a width and height of `1rem`, using `border-radius: 50%` to turn them from squares to circles.
4. `margin: 3rem 0.2rem` specifies that each circle has a top/bottom margin of `3rem` and left/right margin of `0.2rem` so that they do not directly touch each other, giving them some breathing room.
5. `animation` is a shorthand property for the various animation properties: `animation-name`, `animation-duration`, `animation-iteration-count`, `animation-direction` are used.
6. `nth-child(n)` targets the element which is the nth child of its parent.
7. `animation-delay` is used on the second and third `div` respectively, so that each element does not start the animation at the same time.
#### Browser support
100.0%
- https://caniuse.com/#feat=css-animation
[⬆ Back to top](#contents)
### Button border animation
Creates a border animation on hover.
```html
```
```css
.button {
background-color: #c47135;
border: none;
color: #ffffff;
outline: none;
padding: 12px 40px 10px;
position: relative;
}
.button:before,
.button:after {
border: 0 solid transparent;
transition: all 0.25s;
content: '';
height: 24px;
position: absolute;
width: 24px;
}
.button:before {
border-top: 2px solid #c47135;
left: 0px;
top: -5px;
}
.button:after {
border-bottom: 2px solid #c47135;
bottom: -5px;
right: 0px;
}
.button:hover {
background-color: #c47135;
}
.button:hover:before,
.button:hover:after {
height: 100%;
width: 100%;
}
```
#### Explanation
- Use the `:before` and `:after` pseduo-elements as borders that animate on hover.
#### Browser support
100.0%
[⬆ Back to top](#contents)
### Donut spinner
Creates a donut spinner that can be used to indicate the loading of content.
```html
```
```css
@keyframes donut-spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.donut {
display: inline-block;
border: 4px solid rgba(0, 0, 0, 0.1);
border-left-color: #7983ff;
border-radius: 50%;
width: 30px;
height: 30px;
animation: donut-spin 1.2s linear infinite;
}
```
#### Explanation
- Use a semi-transparent `border` for the whole element, except one side that will serve as the loading indicator for the donut. Use `animation` to rotate the element.
#### Browser support
100.0%
⚠️ Requires prefixes for full support.
- https://caniuse.com/#feat=css-animation
- https://caniuse.com/#feat=transforms2d
[⬆ Back to top](#contents)
### Easing variables
Variables that can be reused for `transition-timing-function` properties, more
powerful than the built-in `ease`, `ease-in`, `ease-out` and `ease-in-out`.
```html
Hover
```
```css
:root {
/* Place variables in here to use globally */
}
.easing-variables {
--ease-in-quad: cubic-bezier(0.55, 0.085, 0.68, 0.53);
--ease-in-cubic: cubic-bezier(0.55, 0.055, 0.675, 0.19);
--ease-in-quart: cubic-bezier(0.895, 0.03, 0.685, 0.22);
--ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06);
--ease-in-expo: cubic-bezier(0.95, 0.05, 0.795, 0.035);
--ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.335);
--ease-out-quad: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--ease-out-cubic: cubic-bezier(0.215, 0.61, 0.355, 1);
--ease-out-quart: cubic-bezier(0.165, 0.84, 0.44, 1);
--ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1);
--ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
--ease-out-circ: cubic-bezier(0.075, 0.82, 0.165, 1);
--ease-in-out-quad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
--ease-in-out-cubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--ease-in-out-quart: cubic-bezier(0.77, 0, 0.175, 1);
--ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1);
--ease-in-out-expo: cubic-bezier(1, 0, 0, 1);
--ease-in-out-circ: cubic-bezier(0.785, 0.135, 0.15, 0.86);
display: inline-block;
width: 75px;
height: 75px;
padding: 10px;
color: white;
line-height: 50px;
text-align: center;
background: #333;
transition: transform 1s var(--ease-out-quart);
}
.easing-variables:hover {
transform: rotate(45deg);
}
```
#### Explanation
- The variables are defined globally within the `:root` CSS pseudo-class which matches the root element of a tree representing the document.
- In HTML, `:root` represents the `` element and is identical to the selector `html`, except that its specificity is higher.
#### Browser support
96.5%
- https://caniuse.com/#feat=css-variables
[⬆ Back to top](#contents)
### Height transition
Transitions an element's height from `0` to `auto` when its height is unknown.
```html
Hover me to see a height transition.
content
```
```css
.el {
transition: max-height 0.5s;
overflow: hidden;
max-height: 0;
}
.trigger:hover > .el {
max-height: var(--max-height);
}
```
```js
var el = document.querySelector('.el')
var height = el.scrollHeight
el.style.setProperty('--max-height', height + 'px')
```
#### Explanation
1. `transition: max-height: 0.5s cubic-bezier(...)` specifies that changes to `max-height` should be transitioned over 0.5 seconds, using an `ease-out-quint` timing function.
2. `overflow: hidden` prevents the contents of the hidden element from overflowing its container.
3. `max-height: 0` specifies that the element has no height initially.
4. `.target:hover > .el` specifies that when the parent is hovered over, target a child `.el` within it and use the `--max-height` variable which was defined by JavaScript.
---
1. `el.scrollHeight` is the height of the element including overflow, which will change dynamically based on the content of the element.
2. `el.style.setProperty(...)` sets the `--max-height` CSS variable which is used to specify the `max-height` of the element the target is hovered over, allowing it to transition smoothly from 0 to auto.
#### Browser support
96.5%
Requires JavaScript
⚠️ Causes reflow on each animation frame, which will be laggy if there are a large number of elements
beneath the element that is transitioning in height.
- https://caniuse.com/#feat=css-variables
- https://caniuse.com/#feat=css-transitions
[⬆ Back to top](#contents)
### Hover shadow box animation
Creates a shadow box around the text when it is hovered.
```html
Box it!
```
```css
.hover-shadow-box-animation {
display: inline-block;
vertical-align: middle;
transform: perspective(1px) translateZ(0);
box-shadow: 0 0 1px transparent;
margin: 10px;
transition-duration: 0.3s;
transition-property: box-shadow, transform;
}
.hover-shadow-box-animation:hover,
.hover-shadow-box-animation:focus,
.hover-shadow-box-animation:active {
box-shadow: 1px 10px 10px -10px rgba(0, 0, 24, 0.5);
transform: scale(1.2);
}
```
#### Explanation
1. `display: inline-block` to set width and length for `p` element thus making it an `inline-block`.
2. Set `transform: perspective(1px)` to give element a 3D space by affecting the distance between the Z plane and the user and `translate(0)` to reposition the `p` element along z-axis in 3D space.
3. `box-shadow:` to set up the box.
4. `transparent` to make box transparent.
5. `transition-property` to enable transitions for both `box-shadow` and `transform`.
6. `:hover` to activate whole css when hovering is done until `active`.
7. `transform: scale(1.2)` to change the scale, magnifying the text.
#### Browser support
100.0%
- https://caniuse.com/#feat=transforms3d
- https://caniuse.com/#feat=css-transitions
[⬆ Back to top](#contents)
### Hover underline animation
Creates an animated underline effect when the text is hovered over.
**Credit:** https://flatuicolors.com/
```html
Hover this text to see the effect!
```
```css
.hover-underline-animation {
display: inline-block;
position: relative;
color: #0087ca;
}
.hover-underline-animation::after {
content: '';
position: absolute;
width: 100%;
transform: scaleX(0);
height: 2px;
bottom: 0;
left: 0;
background-color: #0087ca;
transform-origin: bottom right;
transition: transform 0.25s ease-out;
}
.hover-underline-animation:hover::after {
transform: scaleX(1);
transform-origin: bottom left;
}
```
#### Explanation
1. `display: inline-block` makes the block `p` an `inline-block` to prevent the underline from spanning the entire parent width rather than just the content (text).
2. `position: relative` on the element establishes a Cartesian positioning context for pseudo-elements.
3. `::after` defines a pseudo-element.
4. `position: absolute` takes the pseudo element out of the flow of the document and positions it in relation to the parent.
5. `width: 100%` ensures the pseudo-element spans the entire width of the text block.
6. `transform: scaleX(0)` initially scales the pseudo element to 0 so it has no width and is not visible.
7. `bottom: 0` and `left: 0` position it to the bottom left of the block.
8. `transition: transform 0.25s ease-out` means changes to `transform` will be transitioned over 0.25 seconds with an `ease-out` timing function.
9. `transform-origin: bottom right` means the transform anchor point is positioned at the bottom right of the block.
10. `:hover::after` then uses `scaleX(1)` to transition the width to 100%, then changes the `transform-origin` to `bottom left` so that the anchor point is reversed, allowing it transition out in the other direction when hovered off.
#### Browser support
100.0%
- https://caniuse.com/#feat=transforms2d
- https://caniuse.com/#feat=css-transitions
[⬆ Back to top](#contents)
### Pulse loader
Creates a pulse effect loader animation using the `animation-delay` property.
```html
```
```css
.ripple-loader {
position: relative;
width: 64px;
height: 64px;
}
.ripple-loader div {
position: absolute;
border: 4px solid #76ff03;
border-radius: 50%;
animation: ripple-loader 1s ease-out infinite;
}
.ripple-loader div:nth-child(2) {
animation-delay: -0.5s;
}
@keyframes ripple-loader {
0% {
top: 32px;
left: 32px;
width: 0;
height: 0;
opacity: 1;
}
100% {
top: 0;
left: 0;
width: 64px;
height: 64px;
opacity: 0;
}
}
```
#### Explanation
- Use `@keyframes` to define an animation at two points in the cycle, start (`0%`), where the two `
` elements have no `width` or `height` and are positioned at the center and end (`100%`), where both `
` elements have increased `width` and `height`, but their `position` is reset to `0`.
- Use `opacity` to transition from `1` to `0` when animating to give the `
` elements a disappearing effect as they expand.
- `.ripple-loader`, which is the parent container, has a predefined `width` and `height`. It uses `position: relative` to position its children.
- Use `animation-delay` on the second `
` element, so that each element starts its animation at a different time.
#### Browser support
100.0%
- https://caniuse.com/#feat=css-animation
[⬆ Back to top](#contents)
---
## Interactivity
### Disable selection
Makes the content unselectable.
```html
You can select me.
You can't select me!
```
```css
.unselectable {
user-select: none;
}
```
#### Explanation
- `user-select: none` specifies that the text cannot be selected.
#### Browser support
97.5%
⚠️ Requires prefixes for full support. ⚠️ This is not a secure method to prevent users from copying content.
- https://caniuse.com/#feat=user-select-none
[⬆ Back to top](#contents)
### Hamburguer Button
This is a way to build simple hamburger button for menu bar.
```html
```
```css
.hb,
.hb:before,
.hb:after {
position: relative;
width: 30px;
height: 5px;
border: none;
outline: none;
background-color: #333;
border-radius: 3px;
transition: 0.5s;
cursor: pointer;
}
.hb:before,
.hb:after {
content: '';
position: absolute;
top: -7.5px;
left: 0;
}
.hb:after {
top: 7.5px;
}
.hb:hover {
background-color: transparent;
}
.hb:hover:before,
.hb:hover:after {
top: 0;
}
.hb:hover::before {
transform: rotate(45deg);
}
.hb:hover::after {
transform: rotate(-45deg);
}
```
#### Explanation
- Use a `