npm npm npm npm

border-with-top-triangle


  • title: Border with top triangle
  • tags: visual,beginner

Creates a content container with a triangle at the top.

  • Use the :before and :after pseudo-elements to create two triangles.
  • The colors of the two triangles should be the same as the container's border-color and the container's background-color respectively.
  • The border-width of the one triangle (:before) should be 1px wider than the other one (:after), in order to act as the border.
  • The smaller triangle (:after) should be 1px to the right of the larger triangle (:before) to allow for its left border to be shown.
<div class="container">Border with top triangle</div>
.container {
  position: relative;
  background: ##ffffff;
  padding: 15px;
  border: 1px solid ##dddddd;
  margin-top: 20px;
}

.container:before,
.container:after {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 19px;
  border: 11px solid transparent;
  border-bottom-color: ##dddddd;
}

.container:after {
  left: 20px;
  border: 10px solid transparent;
  border-bottom-color: ##ffffff;
}

bouncing-loader


  • title: Bouncing loader
  • tags: animation,intermediate

Creates a bouncing loader animation.

  • Use @keyframes to define an animation with two states, where the element changes opacity and is translated up on the 2D plane using transform: translate3d(). Use a single axis translation on transform: translate3d() to achieve better animation performance.
  • Create a parent container, .bouncing-loader, for the bouncing circles and use display: flex and justify-content: center to position them in the center.
  • Give the three bouncing circle <div> elements a width and height of 16px and use border-radius: 50% to make them circular.
  • Apply the bouncing-loader animation to each of the three bouncing circles, using a different animation-delay for each one and animation-direction: alternate to create the appropriate effect.
<div class="bouncing-loader">
  <div></div>
  <div></div>
  <div></div>
</div>
@keyframes bouncing-loader {
  to {
    opacity: 0.1;
    transform: translate3d(0, -16px, 0);
  }
}

.bouncing-loader {
  display: flex;
  justify-content: center;
}

.bouncing-loader > div {
  width: 16px;
  height: 16px;
  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;
}

box-sizing-reset


  • title: Box-sizing reset
  • tags: layout,beginner

Resets the box-model so that width and height are not affected by border or padding.

  • Use box-sizing: border-box to include the width and height of padding and border when calculating the element's width and height.
  • Use box-sizing: inherit to pass down the box-sizing property from parent to child elements.
<div class="box">border-box</div>
<div class="box content-box">content-box</div>
div {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

.box {
  display: inline-block;
  width: 120px;
  height: 120px;
  padding: 8px;
  margin: 8px;
  background: ##F24333;
  color: white;
  border: 1px solid ##BA1B1D;
  border-radius: 4px;
}

.content-box {
  box-sizing: content-box;
}

button-border-animation


  • title: Button border animation
  • tags: animation,intermediate

Creates a border animation on hover.

  • Use the :before and :after pseudo-elements to create two boxes 24px wide opposite each other above and below the box.
  • Use the :hover pseudo-class to extend the width of those elements to 100% on hover and animate the change using transition.
<button class="animated-border-button">Submit</button>
.animated-border-button {
  background-color: ##141414;
  border: none;
  color: ##ffffff;
  outline: none;
  padding: 12px 40px 10px;
  position: relative;
}

.animated-border-button:before,
.animated-border-button:after {
  border: 0 solid transparent;
  transition: all 0.3s;
  content: '';
  height: 0;
  position: absolute;
  width: 24px;
}

.animated-border-button:before {
  border-top: 2px solid ##141414;
  right: 0;
  top: -4px;
}

.animated-border-button:after {
  border-bottom: 2px solid ##141414;
  bottom: -4px;
  left: 0;
}

.animated-border-button:hover:before,
.animated-border-button:hover:after {
  width: 100%;
}

checkerboard-pattern


  • title: Checkerboard background pattern
  • tags: visual,intermediate

Creates a checkerboard background pattern.

  • Use background-color to set a white background.
  • Use background-image with two linear-gradient() values, each one with a different angle to create the checkerboard pattern.
  • Use background-size to specify the pattern's size.
  • Note: The fixed height and width of the element is for demonstration purposes only.
<div class="checkerboard"></div>
.checkerboard {
  width: 240px;
  height: 240px;
  background-color: ##fff;
  background-image: linear-gradient(
      45deg,
      ##000 25%,
      transparent 25%,
      transparent 75%,
      ##000 75%,
      ##000
    ),
    linear-gradient(
      -45deg,
      ##000 25%,
      transparent 25%,
      transparent 75%,
      ##000 75%,
      ##000
    );
  background-size: 60px 60px;
  background-repeat: repeat;
}

circle


  • title: Circle
  • tags: visual,beginner

Creates a circular shape with pure CSS.

  • Use border-radius: 50% to curve the borders of the element to create a circle.
  • Since a circle has the same radius at any given point, the width and height must be the same. Differing values will create an ellipse.
<div class="circle"></div>
.circle {
  border-radius: 50%;
  width: 32px;
  height: 32px;
  background: ##9C27B0;
}

clearfix


  • title: Clearfix
  • tags: layout,beginner

Ensures that an element self-clears its children.

  • Use the :after pseudo-element and apply content: '' to allow it to affect layout.
  • Use clear: both to make the element clear past both left and right floats.
  • For this technique to work properly, make sure there are no non-floating children in the container and that there are no tall floats before the clearfixed container but in the same formatting context (e.g. floated columns).
  • Note: This is only useful if you are using float to build layouts. Consider using a more modern approach, such as the flexbox or grid layout.
<div class="clearfix">
  <div class="floated">float a</div>
  <div class="floated">float b</div>
  <div class="floated">float c</div>
</div>
.clearfix:after {
  content: '';
  display: block;
  clear: both;
}

.floated {
  float: left;
  padding: 4px;
}

constant-width-to-height-ratio


  • title: Constant width to height ratio
  • tags: layout,beginner

Ensures that an element with variable width will retain a proportionate height value.

  • Apply padding-top on the :before pseudo-element, making the height of the element equal to a percentage of its width.
  • The proportion of height to width can be altered as necessary. For example a padding-top of 100% will create a responsive square (1:1 ratio).
<div class="constant-width-to-height-ratio"></div>
.constant-width-to-height-ratio {
  background: ##9C27B0;
  width: 50%;
}

.constant-width-to-height-ratio:before {
  content: '';
  padding-top: 100%;
  float: left;
}

.constant-width-to-height-ratio:after {
  content: '';
  display: block;
  clear: both;
}

counter


  • title: Counter
  • tags: visual,advanced

Creates a custom list counter that accounts for nested list elements.

  • Use counter-reset to initialize a variable counter (default 0), the name of which is the value of the attribute (i.e. counter).
  • Use counter-increment on the variable counter for each countable element (i.e. each <li>).
  • Use counters() to display the value of each variable counter as part of the content of the :before pseudo-element for each countable element (i.e. each <li>). The second value passed to it ('.') acts as the delimiter for nested counters.
<ul>
  <li>List item</li>
  <li>List item</li>
  <li>
    List item
    <ul>
      <li>List item</li>
      <li>List item</li>
      <li>List item</li>
    </ul>
  </li>
</ul>
ul {
  counter-reset: counter;
  list-style: none;
}

li:before {
  counter-increment: counter;
  content: counters(counter, '.') ' ';
}

custom-scrollbar


  • title: Custom scrollbar
  • tags: visual,advanced

Customizes the scrollbar style for the an elements with scrollable overflow.

  • Use ::-webkit-scrollbar to style the scrollbar element.
  • Use ::-webkit-scrollbar-track to style the scrollbar track (the background of the scrollbar).
  • Use ::-webkit-scrollbar-thumb to style the scrollbar thumb (the draggable element).
  • Note: Scrollbar styling doesn't appear to be on any standards track. This technique only works on WebKit-based browsers.
<div class="custom-scrollbar">
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit.<br />
    Iure id exercitationem nulla qui repellat laborum vitae, <br />
    molestias tempora velit natus. Quas, assumenda nisi. <br />
    Quisquam enim qui iure, consequatur velit sit?
  </p>
</div>
.custom-scrollbar {
  height: 70px;
  overflow-y: scroll;
}

.custom-scrollbar::-webkit-scrollbar {
  width: 8px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: ##1E3F20;
  border-radius: 12px;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: ##4A7856;
  border-radius: 12px;
}

custom-text-selection


  • title: Custom text selection
  • tags: visual,beginner

Changes the styling of text selection.

  • Use the ::selection pseudo-selector to style text within it when selected.
<p class="custom-text-selection">Select some of this text.</p>
::selection {
  background: aquamarine;
  color: black;
}

.custom-text-selection::selection {
  background: deeppink;
  color: white;
}

disable-selection


  • title: Disable selection
  • tags: interactivity,beginner

Makes the content unselectable.

  • Use user-select: none to make the content of the element not selectable.
  • Note: This is not a secure method to prevent users from copying content.
<p>You can select me.</p>
<p class="unselectable">You can't select me!</p>
.unselectable {
  user-select: none;
}

display-table-centering


  • title: Display table centering
  • tags: layout,intermediate

Vertically and horizontally centers a child element within its parent element, using display: table.

  • Use display: table to make the .center element behave like a <table> element.
  • Set height and width to 100% to make the element fill the available space within its parent element.
  • Use display: table-cell on the child element to make it behave like a <td> elements.
  • Use text-align: center and vertical-align: middle on the child element to center it horizontally and vertically.
  • The outer parent (.container) must have a fixed width and height.
<div class="container">
  <div class="center"><span>Centered content</span></div>
</div>
.container {
  border: 1px solid ##9C27B0;
  height: 250px;
  width: 250px;
}

.center {
  display: table;
  height: 100%;
  width: 100%;
}

.center > span {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

donut-spinner


  • title: Donut spinner
  • tags: animation,intermediate

Creates a donut spinner that can be used to indicate the loading of content.

  • Use a semi-transparent border for the whole element, except one side that will serve as the loading indicator for the donut.
  • Define and use an appropriate animation, using transform: rotate() to rotate the element.
<div class="donut"></div>
@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;
}

drop-cap


  • title: Drop cap
  • tags: visual,beginner

Makes the first letter of the first paragraph bigger than the rest of the text.

  • Use the :first-child selector to select only the first paragraph.
  • Use the ::first-letter pseudo-element to style the first element of the paragraph.
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam commodo ligula quis tincidunt cursus. Integer consectetur tempor ex eget hendrerit. Cras facilisis sodales odio nec maximus. Pellentesque lacinia convallis libero, rhoncus tincidunt ante dictum at. Nullam facilisis lectus tellus, sit amet congue erat sodales commodo.</p>
<p>Donec magna erat, imperdiet non odio sed, sodales tempus magna. Integer vitae orci lectus. Nullam consectetur orci at pellentesque efficitur.</p>
p:first-child::first-letter {
  color: ##5f79ff;
  float: left;
  margin: 0 8px 0 4px;
  font-size: 3rem;
  font-weight: bold;
  line-height: 1;
}

dynamic-shadow


  • title: Dynamic shadow
  • tags: visual,intermediate

Creates a shadow similar to box-shadow but based on the colors of the element itself.

  • Use the :after pseudo-element with position: absolute and width and height equal to 100% to fill the available space in the parent element.
  • Use background: inherit to inherit the background of the parent element.
  • Use top to slightly offset the pseudo-element, filter: blur() to create a shadow and opacity to make it semi-transparent.
  • Use z-index: 1 on the parent and z-index: -1 on the pseudo-element to position it behind its parent.
<div class="dynamic-shadow"></div>
.dynamic-shadow {
  position: relative;
  width: 10rem;
  height: 10rem;
  background: linear-gradient(75deg, ##6d78ff, ##00ffb8);
  z-index: 1;
}

.dynamic-shadow:after {
  content: '';
  width: 100%;
  height: 100%;
  position: absolute;
  background: inherit;
  top: 0.5rem;
  filter: blur(0.4rem);
  opacity: 0.7;
  z-index: -1;
}

etched-text


  • title: Etched text
  • tags: visual,intermediate

Creates an effect where text appears to be "etched" or engraved into the background.

  • Use text-shadow to create a white shadow offset 0px horizontally and 2px vertically from the origin position.
  • The background must be darker than the shadow for the effect to work.
  • The text color should be slightly faded to make it look like it's engraved/carved out of the background.
<p class="etched-text">I appear etched into the background.</p>
.etched-text {
  text-shadow: 0 2px white;
  font-size: 1.5rem;
  font-weight: bold;
  color: ##b8bec5;
}

evenly-distributed-children


  • title: Evenly distributed children
  • tags: layout,intermediate

Evenly distributes child elements within a parent element.

  • Use display: flex to use the flexbox layout.
  • Use justify-content: space-between to evenly distributes child elements horizontally. The first item is positioned at the left edge, while the last item is positioned at the right edge.
  • Alternatively, you can use justify-content: space-around to distribute the children with space around them, rather than between them.
<div class="evenly-distributed-children">
  <p>Item1</p>
  <p>Item2</p>
  <p>Item3</p>
</div>
.evenly-distributed-children {
  display: flex;
  justify-content: space-between;
}

fit-image-in-container


  • title: Fit image in container
  • tags: layout,visual,intermediate

Fits an positions an image appropriately inside its container while preserving its aspect ratio.

  • Use object-fit: contain to fit the entire image within the container while preserving its aspect ratio.
  • Use object-fit: cover to fill the container with the image while preserving its aspect ratio.
  • Use object-position: center to position the image at the center of the container.
<img class="image image-contain" src="https://picsum.photos/600/200" />
<img class="image image-cover" src="https://picsum.photos/600/200" />
.image {
  background: ##34495e;
  border: 1px solid ##34495e;
  width: 200px;
  height: 200px;
}

.image-contain {
  object-fit: contain;
  object-position: center;
}

.image-cover {
  object-fit: cover;
  object-position: right top;
}

flexbox-centering


  • title: Flexbox centering
  • tags: layout,beginner

Horizontally and vertically centers a child element within a parent element using flexbox.

  • Use display: flex to create a flexbox layout.
  • Use justify-content: center to center the child horizontally.
  • Use align-items: center to center the child vertically.
<div class="flexbox-centering">
  <div>Centered content.</div>
</div>
.flexbox-centering {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100px;
}

floating-list-titles


  • title: List with floating section headings
  • tags: visual,advanced

Creates a list with floating headings for each section.

  • Use overflow-y: auto to allow the list container to overflow vertically.
  • Use display: grid on the inner container (<dl>) to create a layout with two columns.
  • Set headings (<dt>) to grid-column: 1 and content (<dd>) to grid-column: 2
  • Finally, apply position: sticky and top: 0.5rem to headings to create a floating effect.
<div class="container">
  <div class="floating-stack">
    <dl>
      <dt>A</dt>
      <dd>Algeria</dd>
      <dd>Angola</dd>

      <dt>B</dt>
      <dd>Benin</dd>
      <dd>Botswana</dd>
      <dd>Burkina Faso</dd>
      <dd>Burundi</dd>

      <dt>C</dt>
      <dd>Cabo Verde</dd>
      <dd>Cameroon</dd>
      <dd>Central African Republic</dd>
      <dd>Chad</dd>
      <dd>Comoros</dd>
      <dd>Congo, Democratic Republic of the</dd>
      <dd>Congo, Republic of the</dd>
      <dd>Cote d'Ivoire</dd>

      <dt>D</dt>
      <dd>Djibouti</dd>

      <dt>E</dt>
      <dd>Egypt</dd>
      <dd>Equatorial Guinea</dd>
      <dd>Eritrea</dd>
      <dd>Eswatini (formerly Swaziland)</dd>
      <dd>Ethiopia</dd>
    </dl>
  </div>
</div>
.container {
  display: grid;
  place-items: center;
  min-height: 400px;
}

.floating-stack {
  background: ##455A64;
  color: ##fff;
  height: 80vh;
  height: 320px;
  border-radius: 1rem;
  overflow-y: auto;
}

.floating-stack > dl {
  margin: 0 0 1rem;
  display: grid;
  grid-template-columns: 2.5rem 1fr;
  align-items: center;
}

.floating-stack dt {
  position: sticky;
  top: 0.5rem;
  left: 0.5rem;
  font-weight: bold;
  background: ##263238;
  color: ##cfd8dc;
  height: 2rem;
  width: 2rem;
  border-radius: 50%;
  padding: 0.25rem 1rem;
  grid-column: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
}

.floating-stack dd {
  grid-column: 2;
  margin: 0;
  padding: 0.75rem;
}

.floating-stack > dl:first-of-type > dd:first-of-type {
  margin-top: 0.25rem;
}

focus-within


  • title: Focus Within
  • tags: visual,interactivity,intermediate

Changes the appearance of a form if any of its children are focused.

  • Use the pseudo-class :focus-within to apply styles to a parent element if any child element gets focused.
<form>
  <label for="username">Username:</label>
  <input id="username" type="text" />
  <br />
  <label for="password">Password:</label>
  <input id="password" type="text" />
</form>
form {
  border: 2px solid ##52B882;
  padding: 8px;
  border-radius: 2px;
}

form:focus-within {
  background: ##7CF0BD;
}

label {
  display: inline-block;
  width: 72px;
}

input {
  margin: 4px 12px;
}

full-width


  • title: Full-width image
  • tags: layout,intermediate

Creates a full-width image.

  • Use left: 50% and right: 50% to position the image in the middle of the parent element.
  • Use margin-left: -50vw and margin-right: -50vw to offset the image on both sides relative to the size of the viewport.
  • Use width: 100vw and max-width: 100vw to size the image relative to the viewport.
<main>
  <h4>Lorem ipsum dolor sit amet</h4>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris molestie
    lobortis sapien, sit amet iaculis est interdum tincidunt. Nunc egestas nibh
    ut metus elementum consequat. Integer elit orci, rhoncus efficitur lectus
    eu, faucibus interdum felis.
  </p>
  <p>
    <img class="full-width" src="https://picsum.photos/id/257/2560/1440.jpg" />
  </p>
  <p>
    Orci varius natoque penatibus et magnis dis parturient montes, nascetur
    ridiculus mus. Nullam pretium lectus sed ex efficitur, ac varius sapien
    gravida. Sed facilisis elit quis sem sollicitudin, ut aliquam neque
    eleifend. Maecenas sagittis neque sapien, ac tempus nulla tempus nec.
    Curabitur tellus est, convallis id dolor ut, porta hendrerit quam.
  </p>
</main>
main {
  margin: 0 auto;
  max-width: 640px;
}

img {
  height: auto;
  max-width: 100%;
}

.full-width {
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  max-width: 100vw;
  width: 100vw;
}

fullscreen


  • title: Fullscreen
  • tags: visual,advanced

Applies styles to an element when in fullscreen mode.

The :fullscreen CSS pseudo-element represents an element that's displayed when the browser is in fullscreen mode.

  • Use the :fullscreen CSS pseudo-element selector to select and style an element that is displayed in fullscreen mode.
  • Use a <button> and Element.requestFullscreen() to create a button that makes the element fullscreen for the purposes of previewing the style.
<div class="container">
  <p><em>Click the button below to enter the element into fullscreen mode. </em></p>
  <div class="element" id="element"><p>I change color in fullscreen mode!</p></div>
  <br />
  <button onclick="var el = document.getElementById('element'); el.requestFullscreen();">
    Go Full Screen!
  </button>
</div>
.container {
  margin: 40px auto;
  max-width: 700px;
}

.element {
  padding: 20px;
  height: 300px;
  width: 100%;
  background-color: skyblue;
  box-sizing: border-box;
}

.element p {
  text-align: center;
  color: white;
  font-size: 3em;
}

.element:-ms-fullscreen p {
  visibility: visible;
}

.element:fullscreen {
  background-color: ##e4708a;
  width: 100vw;
  height: 100vh;
}

gradient-text


  • title: Gradient text
  • tags: visual,intermediate

Gives text a gradient color.

  • Use background with a linear-gradient value to give the text element a gradient background.
  • Use webkit-text-fill-color: transparent to fill the text with a transparent color.
  • Use webkit-background-clip: text to clip the background with the text, filling the text with the gradient background as the color.
<p class="gradient-text">Gradient text</p>
.gradient-text {
  background: linear-gradient(##70D6FF, ##00072D);
  -webkit-text-fill-color: transparent;
  -webkit-background-clip: text;
  font-size: 32px;
}

grid-centering


  • title: Grid centering
  • tags: layout,beginner

Horizontally and vertically centers a child element within a parent element using grid.

  • Use display: grid to create a grid layout.
  • Use justify-content: center to center the child horizontally.
  • Use align-items: center to center the child vertically.
<div class="grid-centering">
  <div class="child">Centered content.</div>
</div>
.grid-centering {
  display: grid;
  justify-content: center;
  align-items: center;
  height: 100px;
}

hamburger-button


  • title: Hamburger Button
  • tags: interactivity,intermediate

Displays a hamburger menu which transitions to a cross button on hover.

  • Use a .hamburger-menu container div which contains the top, bottom, and middle bars.
  • Set the container to display: flex with flex-flow: column wrap.
  • Add distance between the bars using justify-content: space-between.
  • Use transform: rotate() to rotate the top and bottom bars by 45 degrees and opacity: 0 to fade the middle bar on hover.
  • Use transform-origin: left so that the bars rotate around the left point.
<div class="hamburger-menu">
  <div class="bar top"></div>
  <div class="bar middle"></div>
  <div class="bar bottom"></div>
</div>
.hamburger-menu {
  display: flex;
  flex-flow: column wrap;
  justify-content: space-between;
  height: 2.5rem;
  width: 2.5rem;
  cursor: pointer;
}

.hamburger-menu .bar {
  height: 5px;
  background: black;
  border-radius: 5px;
  margin: 3px 0px;
  transform-origin: left;
  transition: all 0.5s;
}

.hamburger-menu:hover .top {
  transform: rotate(45deg);
}

.hamburger-menu:hover .middle {
  opacity: 0;
}

.hamburger-menu:hover .bottom {
  transform: rotate(-45deg);
}

height-transition


  • title: Height transition
  • tags: animation,intermediate

Transitions an element's height from 0 to auto when its height is unknown.

  • Use transition to specify that changes to max-height should be transitioned over.
  • Use overflow: hidden to prevent the contents of the hidden element from overflowing its container.
  • Use max-height to specify an initial height of 0.
  • Use the :hover pseudo-class to change the max-height to the value of the --max-height variable set by JavaScript.
  • Use Element.scrollHeight and CSSStyleDeclaration.setProperty() to set the value of --max-height to the current height of the element.
  • Note: 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.
<div class="trigger">
  Hover me to see a height transition.
  <div class="el">Additional content</div>
</div>
.el {
  transition: max-height 0.3s;
  overflow: hidden;
  max-height: 0;
}

.trigger:hover > .el {
  max-height: var(--max-height);
}
let el = document.querySelector('.el');
let height = el.scrollHeight;
el.style.setProperty('--max-height', height + 'px');

horizontal-scroll-snap


  • title: Horizontal scroll snap
  • tags: interactivity,intermediate

Creates a horizontally scrollable container that will snap on elements when scrolling.

  • Use display: grid and grid-auto-flow: column to create a horizontal layout.
  • Use scroll-snap-type: x mandatory and overscroll-behavior-x: contain to create a snap effect on horizontal scroll.
  • You can use scroll-snap-align with either start, stop or center to change the snap alignment.
<div class="horizontal-snap">
  <a href="##"><img src="https://picsum.photos/id/1067/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/122/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/188/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/249/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/257/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/259/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/283/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/288/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/299/640/640"></a>
</div>
.horizontal-snap {
  margin: 0 auto;
  display: grid;
  grid-auto-flow: column;
  gap: 1rem;
  height: calc(180px + 1rem);
  padding: 1rem;
  width: 480px;
  overflow-y: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

.horizontal-snap > a {
  scroll-snap-align: center;
}

.horizontal-snap img {
  width: 180px;
  max-width: none;
  object-fit: contain;
  border-radius: 1rem;
}

hover-additional-content


  • title: Show additional content on hover
  • tags: visual,intermediate

Creates a card that displays additional content on hover.

  • Use overflow: hidden on the card to hide elements that overflow vertically.
  • Use the :hover and :focus-within pseudo-class selectors to change the card's styling as necessary when it's hovered or it or its contents are focused.
  • Set transition: 0.3s ease all to create a transition effect on hover/focus.
<div class="card">
  <img src="https://picsum.photos/id/404/367/267"/>
  <h3>Lorem ipsum</h3>
  <div class="focus-content">
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.<br/> <a href="##">Link to source</a>
    </p>
  </div>
</div>
.card {
  width: 300px;
  height: 280px;
  padding: 0;
  box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1);
  border-radius: 8px;
  box-sizing: border-box;
  overflow: hidden;
}

.card * {
  transition: 0.3s ease all;
}

.card img {
  margin: 0;
  width: 300px;
  height: 224px;
  object-fit: cover;
  display: block;
}

.card h3 {
  margin: 0;
  padding: 12px 12px 48px;
  line-height: 32px;
  font-weight: 500;
  font-size: 20px;
}

.card .focus-content {
  display: block;
  padding: 8px 12px;
}

.card p {
  margin: 0;
  line-height: 1.5;
}

.card:hover img, .card:focus-within img {
  margin-top: -80px;
}

.card:hover h3, .card:focus-within h3 {
  padding: 8px 12px 0;
}

hover-shadow-box-animation


  • title: Hover shadow box animation
  • tags: animation,intermediate unlisted: true

Creates a shadow box around the text when it is hovered.

  • 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.
  • Use box-shadow to make the box transparent.
  • Use transition-property to enable transitions for both box-shadow and transform.
  • Use the :hover, :active and :focus pseudo-class selectors to apply a new box-shadow and transform: scale(1.2) to change the scale of the text.
<p class="hover-shadow-box-animation">Box it!</p>
.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);
}

hover-underline-animation


  • title: Hover underline animation
  • tags: animation,advanced

Creates an animated underline effect when the text is hovered over.

  • Use display: inline-block to prevent the underline from spanning the entire parent width rather than just the text content.
  • Use the :after pseudo-element with a width of 100% and position: absolute, placing it below the content.
  • Use transform: scaleX(0) to initially hide the pseudo-element.
  • Use the :hover pseudo-class selector to apply transform: scaleX(1) and display the pseudo-element on hover.
  • Animate transform using transform-origin: left and an appropriate transition.
<p class="hover-underline-animation">Hover this text to see the effect!</p>
.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;
}

image-hover-menu


  • title: Menu on image hover
  • tags: layout,animation,intermediate

Displays a menu overlay when the image is hovered.

  • Use a <figure> to wrap the <img> element and a <div> element that will contain the menu links.
  • Use the opacity and right attributes to animate the image on hover, creating a sliding effect.
  • Set the left attribute of the <div> to the negative of the element's width and reset it to 0 when hovering over the parent element to slide in the menu.
  • Use display: flex, flex-direction: column and justify-content: center on the <div> to vertically center the menu items.
<figure class="hover-menu">
	<img src="https://picsum.photos/id/1060/800/480.jpg"/>
	<div>
		<a href="##">Home</a>
		<a href="##">Pricing</a>
		<a href="##">About</a>
	</div>
</figure>
.hover-menu {
  position: relative;
  overflow: hidden;
  margin: 8px;
  min-width: 340px;
  max-width: 480px;
  max-height: 290px;
  width: 100%;
  background: ##000;
  text-align: center;
  box-sizing: border-box;
}

.hover-menu * {
  box-sizing: border-box;
}

.hover-menu img {
  position: relative;
  max-width: 100%;
  top: 0;
  right: 0;
  opacity: 1;
  transition: 0.3s ease-in-out;
}

.hover-menu div {
  position: absolute;
  top: 0;
  left: -120px;
  width: 120px;
  height: 100%;
  padding: 8px 4px;
  background: ##000;
  transition: 0.3s ease-in-out;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.hover-menu div a {
  display: block;
  line-height: 2;
  color: ##fff;
  text-decoration: none;
  opacity: 0.8;
  padding: 5px 15px;
  position: relative;
  transition: 0.3s ease-in-out;
}

.hover-menu div a:hover {
  text-decoration: underline;
}

.hover-menu:hover img {
  opacity: 0.5;
  right: -120px;
}

.hover-menu:hover div {
  left: 0;
  opacity: 1;
}

image-hover-rotate


  • title: Image rotate on hover
  • tags: animation,visual,intermediate

Creates a rotate effect for the image on hover.

  • Use scale and rotate when hovering over the parent element (a <figure>) to animate the image, using the transition property.
  • Use overflow: hidden on the parent container to hide the excess from the image transformation.
<figure class="hover-rotate">
  <img src="https://picsum.photos/id/669/600/800.jpg"/>
</figure>
.hover-rotate {
  overflow: hidden;
  margin: 8px;
  min-width: 240px;
  max-width: 320px;
  width: 100%;
}

.hover-rotate img {
  transition: all 0.3s;
  box-sizing: border-box;
  max-width: 100%;
}

.hover-rotate:hover img {
  transform: scale(1.3) rotate(5deg);
}

image-mosaic


  • title: Responsive image mosaic
  • tags: layout,intermediate

Creates a responsive image mosaic.

  • Use display: grid to create an appropriate responsive grid layout.
  • Use grid-row: span 2 / auto and grid-column: span 2 / auto to create items that span two rows or two columns respectively.
  • Wrap the previous styles into a media query to avoid applying on small screen sizes.
<div class="image-mosaic">
  <div
    class="card card-tall card-wide"
    style="background-image: url('https://picsum.photos/id/564/1200/800')"
  ></div>
  <div
    class="card card-tall"
    style="background-image: url('https://picsum.photos/id/566/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/575/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/626/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/667/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/678/800/530')"
  ></div>
  <div
    class="card card-wide"
    style="background-image: url('https://picsum.photos/id/695/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/683/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/693/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/715/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/610/800/530')"
  ></div>
  <div
    class="card"
    style="background-image: url('https://picsum.photos/id/599/800/530')"
  ></div>
</div>
.image-mosaic {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  grid-auto-rows: 240px;
}

.card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: ##353535;
  font-size: 3rem;
  color: ##fff;
  box-shadow: rgba(3, 8, 20, 0.1) 0px 0.15rem 0.5rem, rgba(2, 8, 20, 0.1) 0px 0.075rem 0.175rem;
  height: 100%;
  width: 100%;
  border-radius: 4px;
  transition: all 500ms;
  overflow: hidden;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  padding: 0;
  margin: 0;
}

@media screen and (min-width: 600px) {
  .card-tall {
    grid-row: span 2 / auto;
  }

  .card-wide {
    grid-column: span 2 / auto;
  }
}

image-overlay-hover


  • title: Image overlay on hover
  • tags: visual,animation,advanced

Displays an image overlay effect on hover.

  • Use the :before and :after pseudo-elements for the top and bottom bars of the overlay respectively, setting their opacity, transform and transition to produce the desired effect.
  • Use the <figcaption> for the text of the overlay, setting display: flex, flex-direction: column and justify-content: center to center the text into the image.
  • Use the :hover pseudo-selector to update the opacity and transform of all the elements and produce the desired effect.
<figure class="hover-img">
  <img src="https://picsum.photos/id/200/440/320.jpg"/>
  <figcaption>
    <h3>Lorem <br/>Ipsum</h3>
  </figcaption>
</figure>
.hover-img {
  background-color: ##000;
  color: ##fff;
  display: inline-block;
  margin: 8px;
  max-width: 320px;
  min-width: 240px;
  overflow: hidden;
  position: relative;
  text-align: center;
  width: 100%;
}

.hover-img * {
  box-sizing: border-box;
  transition: all 0.45s ease;
}

.hover-img:before,
.hover-img:after {
  background-color: rgba(0, 0, 0, 0.5);
  border-top: 32px solid rgba(0, 0, 0, 0.5);
  border-bottom: 32px solid rgba(0, 0, 0, 0.5);
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  content: '';
  transition: all 0.3s ease;
  z-index: 1;
  opacity: 0;
  transform: scaleY(2);
}

.hover-img img {
  vertical-align: top;
  max-width: 100%;
  backface-visibility: hidden;
}

.hover-img figcaption {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  align-items: center;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.1em;
  opacity: 0;
  z-index: 2;
  transition-delay: 0.1s;
  font-size: 24px;
  font-family: sans-serif;
  font-weight: 400;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.hover-img:hover:before,
.hover-img:hover:after {
  transform: scale(1);
  opacity: 1;
}

.hover-img:hover > img {
  opacity: 0.7;
}

.hover-img:hover figcaption {
  opacity: 1;
}

input-with-prefix


  • title: Input with prefix
  • tags: interactivity,visual,intermediate

Creates an input with a visual, non-editable prefix.

  • Use display: flex to create a container element.
  • Remove the border and outline from the <input> field and apply them to the parent element instead to make it look like an input box.
  • Use the :focus-within pseudo-class selector to style the parent element accordingly, when the user interacts with the <input> field.
<div class="input-box">
  <span class="prefix">+30</span>
  <input type="tel" placeholder="210 123 4567"/>
</div>
.input-box {
  display: flex;
  align-items: center;
  max-width: 300px;
  background: ##fff;
  border: 1px solid ##a0a0a0;
  border-radius: 4px;
  padding-left: 0.5rem;
  overflow: hidden;
  font-family: sans-serif;
}

.input-box .prefix {
  font-weight: 300;
  font-size: 14px;
  color: ##999;
}

.input-box input {
  flex-grow: 1;
  font-size: 14px;
  background: ##fff;
  border: none;
  outline: none;
  padding: 0.5rem;
}

.input-box:focus-within {
  border-color: ##777;
}

masonry-layout


  • title: Masonry Layout
  • tags: layout,advanced

Creates a masonry-style layout that is especially useful when working with images.

  • Create a masonry-style layout that consists of "bricks" that fall into each other with either a fixed width (vertical layout) or a fixed height (horizontal layout), forming a perfect fit. Especially useful when working with images.
  • Define .masonry-container, the container for the masonry layout and .masonry-columns an inner container in which .masonry-brick elements will be placed.
  • Apply display: block to .masonry-brick elements to allow the layout to flow properly.
  • Use the :first-child pseudo-element selector to apply a different margin for the first element to account for its positioning.
  • Use CSS variables to allow for greater flexibility within the layout in combination with media queries to ensure that the layout is responsive in different viewport sizes.
<div class="masonry-container">
  <div class="masonry-columns">
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1016/384/256"
      alt="An image"
    />
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1025/495/330"
      alt="Another image"
    />
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1024/192/128"
      alt="Another image"
    />
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1028/518/345"
      alt="One more image"
    />
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1035/585/390"
      alt="And another one"
    />
    <img
      class="masonry-brick"
      src="https://picsum.photos/id/1074/384/216"
      alt="Last one"
    />
  </div>
</div>
/* Container */
.masonry-container {
  --column-count-small: 1;
  --column-count-medium: 2;
  --column-count-large: 3;
  --column-gap: 0.125rem;
  padding: var(--column-gap);
}

/* Columns */
.masonry-columns {
  column-gap: var(--column-gap);
  column-count: var(--column-count-small);
  column-width: calc(1 / var(--column-count-small) * 100%);
}

@media only screen and (min-width: 640px) {
  .masonry-columns {
    column-count: var(--column-count-medium);
    column-width: calc(1 / var(--column-count-medium) * 100%);
  }
}

@media only screen and (min-width: 800px) {
  .masonry-columns {
    column-count: var(--column-count-large);
    column-width: calc(1 / var(--column-count-large) * 100%);
  }
}

/* Bricks */
.masonry-brick {
  width: 100%;
  height: auto;
  margin: var(--column-gap) 0;
  display: block;
}

.masonry-brick:first-child {
  margin: 0 0 var(--column-gap);
}

mouse-cursor-gradient-tracking


  • title: Mouse cursor gradient tracking
  • tags: visual,interactivity,advanced

A hover effect where the gradient follows the mouse cursor.

  • Declare two CSS variables, --x and --y, used to track the position of the mouse on the button.
  • Declare a CSS variable, --size, used to modify the gradient's dimensions.
  • Use background: radial-gradient(circle closest-side, pink, transparent); to create the gradient at the correct position.
  • Use Document.querySelector() and EventTarget.addEventListener() to register a handler for the 'mousemove' event.
  • Use Element.getBoundingClientRect() and CSSStyleDeclaration.setProperty() to update the values of the --x and --y CSS variables.
<button class="mouse-cursor-gradient-tracking">
  <span>Hover me</span>
</button>
.mouse-cursor-gradient-tracking {
  position: relative;
  background: ##7983ff;
  padding: 0.5rem 1rem;
  font-size: 1.2rem;
  border: none;
  color: white;
  cursor: pointer;
  outline: none;
  overflow: hidden;
}

.mouse-cursor-gradient-tracking span {
  position: relative;
}

.mouse-cursor-gradient-tracking:before {
  --size: 0;
  content: '';
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: var(--size);
  height: var(--size);
  background: radial-gradient(circle closest-side, pink, transparent);
  transform: translate(-50%, -50%);
  transition: width 0.2s ease, height 0.2s ease;
}

.mouse-cursor-gradient-tracking:hover:before {
  --size: 200px;
}
let btn = document.querySelector('.mouse-cursor-gradient-tracking');
btn.addEventListener('mousemove', e => {
  let rect = e.target.getBoundingClientRect();
  let x = e.clientX - rect.left;
  let y = e.clientY - rect.top;
  btn.style.setProperty('--x', x + 'px');
  btn.style.setProperty('--y', y + 'px');
});

navigation-list-item-hover-and-focus-effect


  • title: Navigation list item hover and focus effect
  • tags: visual,beginner

Creates a custom hover and focus effect for navigation items, using CSS transformations.

  • Use the :before pseudo-element at the list item anchor to create a hover effect, hide it using transform: scale(0).
  • Use the :hover and :focus pseudo-class selectors to transition to transform: scale(1) and show the pseudo-element with its colored background.
  • Prevent the pseudo-element from covering the anchor element by using z-index.
<nav class="hover-nav">
  <ul>
    <li><a href="##">Home</a></li>
    <li><a href="##">About</a></li>
    <li><a href="##">Contact</a></li>
  </ul>
</nav>
.hover-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

.hover-nav li {
  float: left;
}

.hover-nav li a {
  position: relative;
  display: block;
  color: ##222;
  text-align: center;
  padding: 8px 12px;
  text-decoration: none;
  z-index: 0;
}

li a:before {
  position: absolute;
  content: "";
  width: 100%;
  height: 100%;
  bottom: 0;
  left: 0;
  background-color: ##f6c126;
  z-index: -1;
  transform: scale(0);
  transition: transform 0.5s ease-in-out;
}

li a:hover:before,
li a:focus:before {
  transform: scale(1);
}

offscreen


  • title: Offscreen
  • tags: layout,visual,intermediate

Completely hides an element visually and positionally in the DOM while still allowing it to be accessible.

  • Remove all borders and padding and hide the element's overflow.
  • Use clip to indicate that no part of the element should be shown.
  • Make the height and width of the element 1px and negate them using margin: -1px.
  • Use position: absolute so that the element does not take up space in the DOM.
  • Note: This provides an accessible and layout-friendly alternative to display: none (not readable by screen readers) and visibility: hidden (takes up physical space in the DOM).
<a class="button" href="https://google.com">
  Learn More <span class="offscreen"> about pants</span>
</a>
.offscreen {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}

overflow-scroll-gradient


  • title: Overflow scroll gradient
  • tags: visual,intermediate

Adds a fading gradient to an overflowing element to better indicate there is more content to be scrolled.

  • Use the :after pseudo-element to create a linear-gradient that fades from transparent to white (top to bottom).
  • Use position: absolute, width and height to appropriately place and size the pseudo-element in its parent.
  • Use pointer-events: none to exclude the pseudo-element from mouse events, allowing text behind it to still be selectable/interactive.
<div class="overflow-scroll-gradient">
  <div class="overflow-scroll-gradient-scroller">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. <br />
    Iure id exercitationem nulla qui repellat laborum vitae, <br />
    molestias tempora velit natus. Quas, assumenda nisi. <br />
    Quisquam enim qui iure, consequatur velit sit? <br />
    Lorem ipsum dolor sit amet consectetur adipisicing elit.<br />
    Iure id exercitationem nulla qui repellat laborum vitae, <br />
    molestias tempora velit natus. Quas, assumenda nisi. <br />
    Quisquam enim qui iure, consequatur velit sit?
  </div>
</div>
.overflow-scroll-gradient {
  position: relative;
}

.overflow-scroll-gradient:after {
  content: '';
  position: absolute;
  bottom: 0;
  width: 250px;
  height: 25px;
  background: linear-gradient(transparent, white);
  pointer-events: none;
}

.overflow-scroll-gradient-scroller {
  overflow-y: scroll;
  background: white;
  width: 240px;
  height: 200px;
  padding: 15px;
  line-height: 1.2;
}

polka-dot-pattern


  • title: Polka dot background pattern
  • tags: visual,intermediate

Creates a polka dot background pattern.

  • Use background-color to set a black background.
  • Use background-image with two radial-gradient() values to create two dots.
  • Use background-size to specify the pattern's size and background-position to appropriately place the two gradients.
  • Note: The fixed height and width of the element is for demonstration purposes only.
<div class="polka-dot"></div>
.polka-dot {
  width: 240px;
  height: 240px;
  background-color: ##000;
  background-image: radial-gradient(##fff 10%, transparent 11%),
    radial-gradient(##fff 10%, transparent 11%);
  background-size: 60px 60px;
  background-position: 0 0, 30px 30px;
  background-repeat: repeat;
}

popout-menu


  • title: Popout menu
  • tags: interactivity,intermediate

Reveals an interactive popout menu on hover/focus.

  • Use left: 100% to move the popout menu to the right of the parent.
  • Use visibility: hidden to hide the popout menu initially, allowing for transitions to be applied (unlike display: none).
  • Use the :hover, :focus and :focus-within pseudo-class selectors to apply visibility: visible to the popout menu, displaying it when the parent element is hovered/focused.
<div class="reference" tabindex="0">
  <div class="popout-menu">Popout menu</div>
</div>
.reference {
  position: relative;
  background: tomato;
  width: 100px;
  height: 80px;
}

.popout-menu {
  position: absolute;
  visibility: hidden;
  left: 100%;
  background: ##9C27B0;
  color: white;
  padding: 16px;
}

.reference:hover > .popout-menu,
.reference:focus > .popout-menu,
.reference:focus-within > .popout-menu {
  visibility: visible;
}

pretty-text-underline


  • title: Pretty text underline
  • tags: visual,intermediate

Provides a nicer alternative to text-decoration: underline where descenders do not clip the underline.

  • Use text-shadow to apply 4 values with offsets covering a 4x4 px area, ensuring the underline has a thick shadow that covers the line where descenders clip it. For the best results, use a color that matches the background and adjust the px values for larger fonts.
  • Use background-image with linear-gradient() and currentColor to create an appropriate gradient that will act as the actual underline.
  • Set background-position, background-repeat and background-size to place the gradient in the correct position.
  • Use the ::selection pseudo-class selector to ensure the text shadow does not interfere with text selection.
  • Note: This is natively implemented as text-decoration-skip-ink: auto but it has less control over the underline.
<div class="container">
  <p class="pretty-text-underline">Pretty text underline without clipping descenders.</p>
</div>
.container {
  background: ##f5f6f9;
  color: ##333;
  padding: 8px 0;
}

.pretty-text-underline {
  display: inline;
  text-shadow: 1px 1px ##f5f6f9, -1px 1px ##f5f6f9, -1px -1px ##f5f6f9,
    1px -1px ##f5f6f9;
  background-image: linear-gradient(90deg, currentColor 100%, transparent 100%);
  background-position: bottom;
  background-repeat: no-repeat;
  background-size: 100% 1px;
}

.pretty-text-underline::selection {
  background-color: rgba(0, 150, 255, 0.3);
  text-shadow: none;
}

pulse-loader


  • title: Pulse loader
  • tags: animation,beginner

Creates a pulse effect loader animation using the animation-delay property.

  • Use @keyframes to define an animation at two points in the cycle: at the start (0%), the two <div> elements have no width or height and are positioned at the center and at the end (100%), both <div> 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 <div> elements a disappearing effect as they expand.
  • Set a predefined width and height for the parent container, .ripple-loader and use position: relative to position its children.
  • Use animation-delay on the second <div> element, so that each element starts its animation at a different time.
<div class="ripple-loader">
  <div></div>
  <div></div>
</div>
.ripple-loader {
  position: relative;
  width: 64px;
  height: 64px;
}

.ripple-loader div {
  position: absolute;
  border: 4px solid ##454ADE;
  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;
  }
}

reset-all-styles


  • title: Reset all styles
  • tags: visual,beginner

Resets all styles to default values using only one property.

  • Use the all property to reset all styles (inherited or not) to their default values.
  • Note: This will not affect direction and unicode-bidi properties.
<div class="reset-all-styles">
  <h5>Title</h5>
  <p>
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Iure id
    exercitationem nulla qui repellat laborum vitae, molestias tempora velit
    natus. Quas, assumenda nisi. Quisquam enim qui iure, consequatur velit sit?
  </p>
</div>
.reset-all-styles {
  all: initial;
}

responsive-layout-sidebar


  • title: Responsive layout with sidebar
  • tags: layout,intermediate

Creates a responsive layout with a content area and a sidebar.

  • Use display: grid on the parent container, to create a grid layout.
  • Use minmax() for the second column (sidebar) to allow it to take up between 150px and 20%.
  • Use 1fr for the first column (main content) to take up the rest of the remaining space.
<div class="container">
  <main>
    This element is 1fr large.
  </main>
  <aside>
    Min: 150px / Max: 20%
  </aside>
</div>
.container {
  display: grid;
  grid-template-columns: 1fr minmax(150px, 20%);
  height: 100px;
}

main, aside {
  padding: 12px;
  text-align: center;
}

main {
  background: ##d4f2c4;
}

aside {
  background: ##81cfd9;
}

rotating-card


  • title: Rotating Card
  • tags: animation,advanced

Creates a two sided card which rotates on hover.

  • Set the the backface-visibility of the cards to none.
  • Initially, set rotateY for the back side of the card to -180deg and the front side to 0deg.
  • Upon hover, set rotateY for the front side to 180deg and backside to 0deg.
  • Set the appropriate perspective value to create the rotate effect.
<div class="card">
  <div class="card-side front">
    <div>Front Side</div>
  </div>
  <div class="card-side back">
    <div>Back Side</div>
  </div>
</div>
.card {
  perspective: 150rem;
  position: relative;
  height: 40rem;
  max-width: 400px;
  margin: 2rem;
  box-shadow: none;
  background: none;
}

.card-side {
  height: 35rem;
  border-radius: 15px;
  transition: all 0.8s ease;
  backface-visibility: hidden;
  position: absolute;
  top: 0;
  left: 0;
  width: 80%;
  padding:2rem;
  color: white
}

.card-side.back {
  transform: rotateY(-180deg);
  background-color: ##4158D0;
  background-image: linear-gradient(43deg, ##4158D0 0%,##C850C0 46%, ##FFCC70 100%);
}

.card-side.front {
  background-color: ##0093E9;
  background-image: linear-gradient(160deg, ##0093E9 0%, ##80D0C7 100%);
}

.card:hover .card-side.front {
  transform: rotateY(180deg);
}

.card:hover .card-side.back {
  transform: rotateY(0deg);
}

shape-separator


  • title: Shape separator
  • tags: visual,intermediate unlisted: true

Uses an SVG shape to create a separator between two different blocks.

  • Use the :after pseudo-element to create the separator element.
  • Use background-image to add the SVG (a 24x12 triangle) shape via a data URI. The background image will repeat by default, covering the whole area of the pseudo-element.
  • Use the background of the parent element to set the desired color for the separator.
<div class="shape-separator"></div>
.shape-separator {
  position: relative;
  height: 48px;
  background: ##9C27B0;
}

.shape-separator:after {
  content: '';
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 12'%3E%3Cpath d='m12 0l12 12h-24z' fill='transparent'/%3E%3C/svg%3E");
  position: absolute;
  width: 100%;
  height: 12px;
  bottom: 0;
}

sibling-fade


  • title: Sibling fade
  • tags: interactivity,intermediate

Fades out the siblings of a hovered item.

  • Use a transition to animate changes to opacity.
  • Use the :hover and :not pseudo-class selectors to change the opacity of all elements except for the one the mouse is over to 0.5.
<div class="sibling-fade">
  <span>Item 1</span> <span>Item 2</span> <span>Item 3</span>
  <span>Item 4</span> <span>Item 5</span> <span>Item 6</span>
</div>
span {
  padding: 0 16px;
  transition: opacity 0.3s;
}

.sibling-fade:hover span:not(:hover) {
  opacity: 0.5;
}

staggered-animation


  • title: Staggered animation
  • tags: animation,advanced

Creates a staggered animation for the elements of a list.

  • Set the opacity to 0 and transform to translateX(100%) to make list elements transparent and move them all the way to the right.
  • Specify the appropriate transition properties for list elements, except transition-delay which is specified relative to the --i custom property.
  • Use inline styles to specify a value for --i for each list element, which will in turn be used for transition-delay to create the stagger effect.
  • Use the :checked pseudo-class selector for the checkbox to appropriately style list elements, setting opacity to 1 and transform to translateX(0) to make them appear and slide into view.
<div class="container">
  <input type="checkbox" name="menu" id="menu" class="menu-toggler">
  <label for="menu" class="menu-toggler-label">Menu</label>
  <ul class="stagger-menu">
    <li style="--i: 0">Home</li>
    <li style="--i: 1">Pricing</li>
    <li style="--i: 2">Account</li>
    <li style="--i: 3">Support</li>
    <li style="--i: 4">About</li>
  </ul>
</div>
.container {
  overflow-x: hidden;
  width: 100%;
}

.menu-toggler {
  display: none;
}

.menu-toggler-label {
  cursor: pointer;
  font-size: 20px;
  font-weight: bold;
}

.stagger-menu {
  list-style-type: none;
  margin: 16px 0;
  padding: 0;
}

.stagger-menu li {
  margin-bottom: 8px;
  font-size: 18px;
  opacity: 0;
  transform: translateX(100%);
  transition-property: opacity, transform;
  transition-duration: 0.3s;
  transition-timing-function: cubic-bezier(0.750, -0.015, 0.565, 1.055);
}

.menu-toggler:checked ~ .stagger-menu li {
  opacity: 1;
  transform: translateX(0);
  transition-delay: calc(0.055s * var(--i));
}

sticky-list-titles


  • title: List with sticky section headings
  • tags: visual,intermediate

Creates a list with sticky headings for each section.

  • Use overflow-y: auto to allow the list container (<dl>) to overflow vertically.
  • Set headings (<dt>) position to sticky and apply top: 0 to stick to the top of the container.
<div class="container">
  <dl class="sticky-stack">
    <dt>A</dt>
    <dd>Algeria</dd>
    <dd>Angola</dd>

    <dt>B</dt>
    <dd>Benin</dd>
    <dd>Botswana</dd>
    <dd>Burkina Faso</dd>
    <dd>Burundi</dd>

    <dt>C</dt>
    <dd>Cabo Verde</dd>
    <dd>Cameroon</dd>
    <dd>Central African Republic</dd>
    <dd>Chad</dd>
    <dd>Comoros</dd>
    <dd>Congo, Democratic Republic of the</dd>
    <dd>Congo, Republic of the</dd>
    <dd>Cote d'Ivoire</dd>

    <dt>D</dt>
    <dd>Djibouti</dd>

    <dt>E</dt>
    <dd>Egypt</dd>
    <dd>Equatorial Guinea</dd>
    <dd>Eritrea</dd>
    <dd>Eswatini (formerly Swaziland)</dd>
    <dd>Ethiopia</dd>
  </dl>
</div>
.container {
  display: grid;
  place-items: center;
  min-height: 400px;
}

.sticky-stack {
  background: ##37474f;
  color: ##fff;
  margin: 0;
  height: 320px;
  border-radius: 1rem;
  overflow-y: auto;
}

.sticky-stack dt {
  position: sticky;
  top: 0;
  font-weight: bold;
  background: ##263238;
  color: ##cfd8dc;
  padding: 0.25rem 1rem;
}

.sticky-stack dd {
  margin: 0;
  padding: 0.75rem 1rem;
}

.sticky-stack dd + dt {
  margin-top: 1rem;
}

stripes-pattern


  • title: Stripes background pattern
  • tags: visual,beginner

Creates a stripes background pattern.

  • Use background-color to set a white background.
  • Use background-image with a radial-gradient() value to create a vertical stripe.
  • Use background-size to specify the pattern's size.
  • Note: The fixed height and width of the element is for demonstration purposes only.
<div class="stripes"></div>
.stripes {
  width: 240px;
  height: 240px;
  background-color: ##fff;
  background-image: linear-gradient(90deg, transparent 50%, ##000 50%);
  background-size: 60px 60px;
  background-repeat: repeat;
}

system-font-stack


  • title: System font stack
  • tags: visual,beginner

Uses the native font of the operating system to get close to a native app feel.

  • Define a list of fonts using font-family.
  • The browser looks for each successive font, preferring the first one if possible, and falls back to the next if it cannot find the font (on the system or defined in CSS).
  • -apple-system is San Francisco, used on iOS and macOS (not Chrome however).
  • BlinkMacSystemFont is San Francisco, used on macOS Chrome.
  • 'Segoe UI' is used on Windows 10.
  • Roboto is used on Android.
  • Oxygen-Sans is used on Linux with KDE.
  • Ubuntu is used on Ubuntu (all variants).
  • Cantarell is used on Linux with GNOME Shell.
  • 'Helvetica Neue' and Helvetica is used on macOS 10.10 and below.
  • Arial is a font widely supported by all operating systems.
  • sans-serif is the fallback sans serif font if none of the other fonts are supported.
<p class="system-font-stack">This text uses the system font.</p>
.system-font-stack {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', Helvetica, Arial,
    sans-serif;
}

text-backdrop-overlay


  • title: Image text overlay
  • tags: visual,beginner

Displays a text on top of an image using an overlay.

  • Use backdrop-filter to apply a blur(14px) and brightness(80%) effect to make text readable regardless of background image and color.
<div>
  <h3 class="text-overlay">Hello, World</h3>
  <img src="https://picsum.photos/id/1050/1200/800">
</div>
div {
  position: relative;
}

.text-overlay {
  position: absolute;
  top: 0;
  left: 0;
  padding: 1rem;
  font-size: 2rem;
  font-weight: 300;
  color: white;
  backdrop-filter: blur(14px) brightness(80%);
}

tile-layout-using-inline-block


  • title: 3-tile layout
  • tags: layout,beginner

Aligns items horizontally using display: inline-block to create a 3-tile layout.

  • Use display: inline-block to create a tiled layout, without using float, flex or grid.
  • Use width in combination with calc to divide the width of the container evenly into 3 columns.
  • Set font-size for .tiles to 0 to avoid whitespace and to 20px for <h2> elements to display the text.
  • Note: If you use relative units (e.g. em), using font-size: 0; to fight whitespace between blocks might cause side effects.
<div class="tiles">
  <div class="tile">
    <img src="https://via.placeholder.com/200x150">
    <h2>30 Seconds of CSS</h2>
  </div>
  <div class="tile">
    <img src="https://via.placeholder.com/200x150">
    <h2>30 Seconds of CSS</h2>
  </div>
  <div class="tile">
    <img src="https://via.placeholder.com/200x150">
    <h2>30 Seconds of CSS</h2>
  </div>
</div>
.tiles {
  width: 600px;
  font-size: 0;
  margin: 0 auto;
}

.tile {
  width: calc(600px / 3);
  display: inline-block;
}

.tile h2 {
  font-size: 20px;
}

toggle-switch


  • title: Toggle switch
  • tags: visual,interactivity,beginner

Creates a toggle switch with CSS only.

  • Use the for attribute to associate the <label> with the checkbox <input> element.
  • Use the :after pseudo-element of the <label> to create a circular knob for the switch.
  • Use the :checked pseudo-class selector to change the position of the knob, using transform: translateX(20px) and the background-color of the switch.
  • Use position: absolute and left: -9999px to visually hide the <input> element.
<input type="checkbox" id="toggle" class="offscreen" />
<label for="toggle" class="switch"></label>
.switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 20px;
  background-color: rgba(0, 0, 0, 0.25);
  border-radius: 20px;
  transition: all 0.3s;
}

.switch:after {
  content: '';
  position: absolute;
  width: 18px;
  height: 18px;
  border-radius: 18px;
  background-color: white;
  top: 1px;
  left: 1px;
  transition: all 0.3s;
}

input[type='checkbox']:checked + .switch:after {
  transform: translateX(20px);
}

input[type='checkbox']:checked + .switch {
  background-color: ##7983ff;
}

.offscreen {
  position: absolute;
  left: -9999px;
}

transform-centering


  • title: Transform centering
  • tags: layout,beginner

Vertically and horizontally centers a child element within its parent element using CSS transforms.

  • Set the position of the parent to relative and that of the child to absolute to place it in relation to its parent.
  • Use left: 50% and top: 50% to offset the child 50% from the left and top edge of the containing block.
  • Use transform: translate(-50%, -50%) to negate its position, so that it is vertically and horizontally centered.
  • Note: The fixed height and width of the parent element is for demonstration purposes only.
<div class="parent">
  <div class="child">Centered content</div>
</div>
.parent {
  border: 1px solid ##9C27B0;
  height: 250px;
  position: relative;
  width: 250px;
}

.child {
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  text-align: center;
}

triangle


  • title: Triangle
  • tags: visual,beginner

Creates a triangular shape with pure CSS.

  • Use three borders to create a triangle shape.
  • All borders should have the same border-width (20px).
  • The opposite side of where the triangle points towards (i.e. top if the triangle points downwards) should have the desired border-color, whereas the adjacent borders (i.e. left and right) should have a border-color of transparent.
  • Altering the border-width values will change the proportions of the triangle.
<div class="triangle"></div>
.triangle {
  width: 0;
  height: 0;
  border-top: 20px solid ##9C27B0;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
}

truncate-text-multiline


  • title: Truncate multiline text
  • tags: layout,intermediate

Truncates text that is longer than one line.

  • Use overflow: hidden to prevent the text from overflowing its dimensions.
  • Set a fixed width to ensure the element has at least one constant dimension.
  • Set height: 109.2px as calculated from the font-size, using the formula font-size * line-height * numberOfLines (in this case 26 * 1.4 * 3 = 109.2).
  • Set height: 36.4px as calculated for the gradient container, based on the formula font-size * line-height (in this case 26 * 1.4 = 36.4).
  • Use background with linear-gradient() to create a gradient from transparent to the background-color.
<p class="truncate-text-multiline">
  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
  eirmod tempor invidunt ut labore et.
</p>
.truncate-text-multiline {
  position: relative;
  overflow: hidden;
  display: block;
  height: 109.2px;
  margin: 0 auto;
  font-size: 26px;
  line-height: 1.4;
  width: 400px;
  background: ##f5f6f9;
  color: ##333;
}

.truncate-text-multiline:after {
  content: '';
  position: absolute;
  bottom: 0;
  right: 0;
  width: 150px;
  height: 36.4px;
  background: linear-gradient(to right, rgba(0, 0, 0, 0), ##f5f6f9 50%);
}

truncate-text


  • title: Truncate text
  • tags: layout,beginner

Truncates text that is longer than one line, adding an ellipsis at the end ().

  • Use overflow: hidden to prevent the text from overflowing its dimensions.
  • Use white-space: nowrap to prevent the text from exceeding one line in height.
  • Use text-overflow: ellipsis to make it so that if the text exceeds its dimensions, it will end with an ellipsis.
  • Specify a fixed width for the element to know when to display an ellipsis.
  • Only works for single line elements.
<p class="truncate-text">If I exceed one line's width, I will be truncated.</p>
.truncate-text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  width: 200px;
}

vertical-scroll-snap


  • title: Vertical scroll snap
  • tags: interactivity,intermediate

Creates a scrollable container that will snap on elements when scrolling.

  • Use display: gird and grid-auto-flow: row to create a vertical layout.
  • Use scroll-snap-type: y mandatory and overscroll-behavior-y: contain to create a snap effect on vertical scroll.
  • You can use scroll-snap-align with either start, stop or center to change the snap alignment.
<div class="vertical-snap">
  <a href="##"><img src="https://picsum.photos/id/1067/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/122/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/188/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/249/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/257/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/259/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/283/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/288/640/640"></a>
  <a href="##"><img src="https://picsum.photos/id/299/640/640"></a>
</div>
.vertical-snap {
  margin: 0 auto;
  display: grid;
  grid-auto-flow: row;
  gap: 1rem;
  width: calc(180px + 1rem);
  padding: 1rem;
  height: 480px;
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scroll-snap-type: y mandatory;
}

.vertical-snap > a {
  scroll-snap-align: center;
}

.vertical-snap img {
  width: 180px;
  object-fit: contain;
  border-radius: 1rem;
}

zebra-striped-list


  • title: Zebra striped list
  • tags: visual,beginner

Creates a striped list with alternating background colors.

  • Use the :nth-child(odd) or :nth-child(even) pseudo-class selectors to apply a different background-color to elements that match based on their position in a group of siblings.
  • Note: You can use it to apply different styles to other HTML elements like <div>, <tr>, <p>, <ol>, etc.
<ul>
  <li>Item 01</li>
  <li>Item 02</li>
  <li>Item 03</li>
  <li>Item 04</li>
  <li>Item 05</li>
</ul>
li:nth-child(odd) {
  background-color: ##999;
}

zig-zag-pattern


  • title: Zig zag background pattern
  • tags: visual,advanced

Creates a zig zag background pattern.

  • Use background-color to set a white background.
  • Use background-image with four linear-gradient() values to create the parts of a zig zag pattern.
  • Use background-size to specify the pattern's size and background-position to place the parts of the pattern in the correct locations.
  • Note: The fixed height and width of the element is for demonstration purposes only.
<div class="zig-zag"></div>
.zig-zag {
  width: 240px;
  height: 240px;
  background-color: ##fff;
  background-image: linear-gradient(135deg, ##000 25%, transparent 25%),
    linear-gradient(225deg, ##000 25%, transparent 25%),
    linear-gradient(315deg, ##000 25%, transparent 25%),
    linear-gradient(45deg, ##000 25%, transparent 25%);
  background-position: -30px 0, -30px 0, 0 0, 0 0;
  background-size: 60px 60px;
  background-repeat: repeat;
}