Repository: phuocng/csslayout
Branch: master
Commit: ecf92df03a34
Files: 120
Total size: 424.4 KB
Directory structure:
gitextract_eojep_s2/
├── .gitignore
├── LICENSE
├── README.md
└── contents/
├── accordion.mdx
├── arrow-buttons.mdx
├── avatar-list.mdx
├── avatar.mdx
├── badge.mdx
├── box-selector.mdx
├── breadcrumb.mdx
├── button-with-icon.mdx
├── calendar.mdx
├── card-layout.mdx
├── card.mdx
├── carousel-slider.mdx
├── center-align-one-and-left-align-the-other.mdx
├── centering.mdx
├── chip.mdx
├── circular-navigation.mdx
├── close-button.mdx
├── color-swatch.mdx
├── concave-corners.mdx
├── cookie-banner.mdx
├── corner-ribbon.mdx
├── curved-background.mdx
├── custom-checkbox-button.mdx
├── custom-radio-button.mdx
├── diagonal-section.mdx
├── docked-at-corner.mdx
├── dot-leader.mdx
├── dot-navigation.mdx
├── drawer.mdx
├── drop-area.mdx
├── drop-cap.mdx
├── dropdown.mdx
├── fading-long-section.mdx
├── feature-comparison.mdx
├── feature-list.mdx
├── fixed-at-corner.mdx
├── fixed-at-side.mdx
├── flipping-number.mdx
├── floating-label.mdx
├── folded-corner.mdx
├── folder-structure.mdx
├── frame-corners.mdx
├── full-background.mdx
├── full-screen-menu.mdx
├── grid-lines-background.mdx
├── grid-without-double-borders.mdx
├── holy-grail.mdx
├── indeterminate-progress-bar.mdx
├── initial-avatar.mdx
├── input-addon.mdx
├── inverted-corners.mdx
├── keyboard-shortcut.mdx
├── layered-card.mdx
├── linear-gauge.mdx
├── lined-paper.mdx
├── masonry-grid.mdx
├── media-object.mdx
├── mega-menu.mdx
├── menu.mdx
├── modal.mdx
├── nested-dropdowns.mdx
├── notification.mdx
├── overlay-play-button.mdx
├── pagination.mdx
├── pie-chart.mdx
├── popover-arrow.mdx
├── presence-indicator.mdx
├── previous-next-buttons.mdx
├── price-tag.mdx
├── pricing-table.mdx
├── progress-bar.mdx
├── property-list.mdx
├── questions-and-answers.mdx
├── radial-progress-bar.mdx
├── radio-button-group.mdx
├── radio-switch.mdx
├── rating.mdx
├── resizable-element.mdx
├── ribbon.mdx
├── same-height-columns.mdx
├── search-box.mdx
├── separator.mdx
├── sidebar.mdx
├── simple-grid.mdx
├── slider.mdx
├── speech-bubble.mdx
├── spin-button.mdx
├── spinner.mdx
├── split-navigation.mdx
├── split-screen.mdx
├── stacked-cards.mdx
├── stamp-border.mdx
├── statistic.mdx
├── status-light.mdx
├── stepper-input.mdx
├── sticky-footer.mdx
├── sticky-header.mdx
├── sticky-sections.mdx
├── sticky-table-column.mdx
├── sticky-table-headers.mdx
├── switch.mdx
├── tab.mdx
├── teardrop.mdx
├── three-dimensions-card.mdx
├── timeline.mdx
├── toggle-password-visibility.mdx
├── tooltip.mdx
├── tree-diagram.mdx
├── triangle-buttons.mdx
├── upload-button.mdx
├── validation-icon.mdx
├── video-background.mdx
├── voting.mdx
├── watermark.mdx
├── wizard.mdx
├── zebra-like-background.mdx
└── zigzag-timeline.mdx
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 phuocng
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# CSS Layout
As a front-end engineer, I deal with a lot of layouts and components. While there are plenty of CSS frameworks out there that provide these, I don't always want to include them all in my project.
That's why I've put together a collection of the most popular layouts and components that can be built with pure CSS.
These layouts and components are powered by modern CSS features like flexbox and grid, and can be easily customized to fit your specific needs. By combining them, you can create any possible layout you need.
The best part? This collection has zero dependencies, no frameworks, and no CSS hacks. These are real use cases that can save you time and effort in your projects.
## About
This project is developed by _Nguyen Huu Phuoc_. I love building products and sharing knowledge.
Be my friend on
- [Twitter](https://twitter.com/nghuuphuoc)
- [Github](https://github.com/phuocng)
================================================
FILE: contents/accordion.mdx
================================================
---
category: Display
created: '2019-12-04'
description: Create an accordion with CSS flexbox
keywords: css accordion, css flexbox
thumbnail: /assets/css-layout/thumbnails/accordion.png
title: Accordion
---
## HTML
```html index.html
```
================================================
FILE: contents/carousel-slider.mdx
================================================
---
category: Navigation
created: '2023-10-14'
description: Create a carousel slider with CSS
openGraphCover: /og/css-layout/carousel-slider.png
thumbnail: /assets/css-layout/thumbnails/carousel-slider.png
title: Carousel slider
---
A carousel slider is a component that lets users browse a collection of items, usually images or cards, by sliding them horizontally or vertically. It's commonly used in websites and mobile apps to showcase products, features, or news articles.
You can find carousel sliders in all kinds of websites and apps, like e-commerce platforms, news portals, and social media sites. They offer an interactive and engaging way for users to navigate content without taking up too much screen space.
On top of that, carousel sliders can be customized with different transition effects, autoplay options, and navigation controls. This makes for an even better user experience.
In this post, we'll show you how to create a carousel slider with CSS.
## HTML markup
Let's talk about organizing the markup for a slider with five items. The slider consists of a `div` element with the class `slider__inner` that displays the list of items, each with a `slider__item` class.
```html
```
For simplicity, let's assume all slider items have the same dimensions as the slider container. The `.slider` class sets the dimensions of the slider container to a `width` and `height` of 100%, taking up all available space in its parent element. The `overflow` property is set to `hidden` to ensure that any content that overflows the slider container is not visible.
```css
.slider {
overflow: hidden;
position: relative;
width: 100%;
height: 20rem;
}
```
Meanwhile, the `.slider__inner` class positions the list of items inside the slider container. It has an absolute position with `top` and `left` properties set to 0, placing it at the top left corner of its parent element (the slider container). The `width` and `height` are also set to 100%, filling up all available space inside its parent element.
```css
.slide__inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
```
To position the items inside the slider container, we use absolute positioning with `top`, `left`, `width`, and `height` properties set to 0 and 100% respectively, ensuring that each item takes up all available space inside the slider container.
```css
.slider__item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
```
Now, to achieve the sliding effect, we use the `translateX()` function of CSS `transform` property. This function moves an element horizontally by a given percentage or pixel value. In our case, we want to move each item to the right so that only one item is visible at a time.
```html
1
2
3
4
5
```
To activate a specific item in the carousel slider, we shift the whole inner container to the left by a value that moves the target item into view. One way to achieve this is by setting the `transform` property of the `.slider__inner` element to `translateX(-300%)`. This will move the inner container three times its width to the left, which positions the fourth item at the beginning of the slider.
```html
1
2
3
4
5
```
By adjusting this value, we can easily activate any other item in our carousel slider. This technique allows us to create an interactive and engaging carousel slider that users can navigate through with ease.
## Adding navigation
Now that we have placed the slider items in the right spot, it's time to add navigation so users can easily move between them.
To do this, we'll create an additional element with the `slider__navigation` CSS class. This element contains multiple dots that users can click to jump to the corresponding item.
Here is the updated markup:
```html
```
The `slider__navigation` element has a position of `absolute`, which means it's positioned relative to the nearest positioned ancestor (in this case, the `.slider` element). We set `bottom: 1rem` to position it at the bottom of the slider container, and `left: 50%` is used to center it horizontally.
To center its content horizontally, we use `transform: translateX(-50%)`, which moves it left by half of its own width.
```css
.slider__navigation {
position: absolute;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
}
```
The navigation dots inside the `slider__navigation` are created using individual elements with a class of `slider__dot`. To space them out evenly, we use the CSS property `gap: 0.5rem`, which adds a gap between each item. The items are aligned along the horizontal axis using flexbox properties such as `display: flex`, `align-items: center`, and `justify-content: center`.
```css
.slider__navigation {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
```
The `slider__dot` class is used to style the navigation dots inside the `slider__navigation` element. It has a background color of `rgb(203 213 225)` and a border radius of `50%`, which gives it a circular shape. It also has a `cursor` property set to `pointer`, which changes the mouse cursor when hovering over the element, indicating that it can be clicked. Finally, its dimensions are set to `height: 0.5rem` and `width: 0.5rem`, making it small enough to fit inside the navigation container but large enough to be clickable.
```css
.slider__dot {
background-color: rgb(203 213 225);
border-radius: 50%;
cursor: pointer;
height: 0.5rem;
width: 0.5rem;
}
```
To indicate the currently active dot, we can add a separate class named `slider__dot--active` and apply it to the corresponding dot element. This class will have a different background color than the inactive dots, making it clear which item is currently active.
```css
.slider__dot--active {
background-color: rgb(100 116 139);
}
```
When an item is activated in the slider, we can remove the `slider__dot--active` class from all dots and then add it only to the dot that corresponds to the currently active item. This ensures that only one dot is highlighted at any given time.
## Adding arrows for easy navigation
In addition to the navigation we created earlier, we can further enhance the user experience by adding two buttons that allow users to quickly move to the previous and next items.
Here's the updated markup:
```html
...
```
To create these buttons, we use the `.slider__prev` and `.slider__next` classes. We set their position to absolute so that they're positioned relative to the slider container. We also set the top position to `50%` and use `transform: translateY(-50%)` to center them vertically inside the slider container.
Here's how they are positioned:
```css
.slider__prev,
.slider__next {
position: absolute;
top: 50%;
transform: translateY(-50%);
height: 1rem;
width: 0.5rem;
}
```
To add arrow navigation to the carousel slider, we can use CSS pseudo-elements `::before` and `::after`. These elements allow us to add content before or after an element's content, which in our case will be arrows.
If you're not familiar with how to create arrows using CSS, you can check out this [post](https://phuoc.ng/collection/css-layout/triangle-buttons/) for guidance.
With these CSS rules in place, you should now have fully functional arrow navigation for your carousel slider.
## Demo
Let's take a look at the final result. Check out the code to see how we shifted the whole inner element to activate the fourth item. It's important to note that this is purely for layout purposes only. Clicking on the dots or arrows won't navigate to the corresponding item. Check out this [post](https://phuoc.ng/collection/css-animation/navigate-to-a-specific-item-in-a-carousel-slider/) to learn how we can make it happen.
```css styles.css
.slider {
overflow: hidden;
position: relative;
width: 100%;
height: 20rem;
}
.slider__inner {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.slider__item {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* Demo purpose */
background: rgb(241 245 249);
align-items: center;
display: flex;
justify-content: center;
font-size: 2.5rem;
font-weight: 500;
}
.slider__navigation {
position: absolute;
bottom: 1rem;
left: 50%;
transform: translateX(-50%);
align-items: center;
display: flex;
justify-content: center;
gap: 0.5rem;
}
.slider__dot {
background: rgb(203 213 225);
border-radius: 50%;
cursor: pointer;
height: 0.5rem;
width: 0.5rem;
}
.slider__dot--active {
background: rgb(100 116 139);
}
.slider__prev,
.slider__next {
position: absolute;
top: 50%;
transform: translateY(-50%);
height: 1rem;
width: 0.5rem;
}
.slider__prev::before,
.slider__next::before {
cursor: pointer;
content: '';
position: absolute;
border-style: solid;
height: 0;
width: 0;
}
.slider__prev::before {
border-color: transparent rgb(148 163 184) transparent transparent;
border-width: 0.5rem 0.5rem 0.5rem 0;
}
.slider__next::before {
border-color: transparent transparent transparent rgb(148 163 184);
border-width: 0.5rem 0 0.5rem 0.5rem;
}
.slider__prev {
left: 0.5rem;
}
.slider__next {
right: 0.5rem;
}
```
```html index.html
1
2
3
4
5
```
## See also
- [Dot navigation](https://phuoc.ng/collection/css-layout/dot-navigation/)
- [Fixed at side](https://phuoc.ng/collection/css-layout/fixed-at-side/)
- [Navigate to a specific item in a carousel slider](https://phuoc.ng/collection/css-animation/navigate-to-a-specific-item-in-a-carousel-slider/)
- [Triangle buttons](https://phuoc.ng/collection/css-layout/triangle-buttons/)
================================================
FILE: contents/center-align-one-and-left-align-the-other.mdx
================================================
---
category: Display
created: '2023-08-27'
description: How to center align one element and left align the other
keywords: css flexbox, css grid
openGraphCover: /og/css-layout/center-align-one-left-align-other.png
thumbnail: /assets/css-layout/thumbnails/center-align-one-left-align-other.png
title: Center align one and left align the other
---
Using a single row to display all elements is a common pattern in web design. These elements can be divided into different groups and arranged on the left, center, or right side of the row.
You've probably seen this pattern before, like in a toolbar where the main actions are grouped and displayed at the center. Meanwhile, less important buttons are located on the left side, like a button to toggle the sidebar.
Another example is the header of a web application, where the main title is displayed at the center, and a button to go back to the previous page is on the left side.
In this post, we'll learn how to create this kind of layout. To keep it simple, let's assume that the layout consists of only two elements.
```html
```
## Using CSS flexbox
Initially, our first idea might be to use flexbox to arrange the layout.
```css
.container {
display: flex;
justify-content: center;
}
```
To align the first element to the left and center the remaining items, we can use the margin property. Here's an example:
```css
.container__left {
margin-right: auto;
}
.container__center {
margin-right: auto;
}
```
Let's take a look at what it looks like:
```css demo.css hidden
:root {
--placeholder-size: 1rem;
}
body {
align-items: center;
display: flex;
justify-content: center;
}
.circle {
background-color: rgb(203 213 225);
border-radius: 9999px;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin-right: 0.125rem;
}
.square {
background-color: rgb(203 213 225);
border-radius: 0.25rem;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin: 0 0.125rem;
}
.container {
border: 1px solid rgb(203 213 225);
border-radius: 0.25rem;
padding: 0.5rem;
width: 16rem;
}
.container__left,
.container__center {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.container {
display: flex;
}
.container__left {
margin-right: auto;
}
.container__center {
margin-right: auto;
}
```
```html index.html
```
Unfortunately, our expectation doesn't match reality. The main element is centered only within the available space, not the entire container. Let's move on to the next section to find a solution to this issue.
## Using CSS grid
In addition to CSS flexbox, CSS offers another powerful tool for creating layouts: CSS grid. We can use this technique to solve the issue we talked about earlier.
Let's say we now have three elements in our layout instead of two, and we need to add an empty element on the right-hand side.
```css
.container {
display: grid;
grid-template-columns: 1fr repeat(1, auto) 1fr;
}
```
Let's dive into some CSS talk. The first CSS declaration is simple: it replaces the `flex` value with `grid`, which tells the browser to create a grid layout.
Now, the second CSS declaration might seem confusing, but it's actually quite easy to understand. The `1fr` means that the first and last columns should take up an equal amount of space. The `repeat(1, auto)` declaration means that there should be one column with a width of `auto`.
So, in simpler terms, this CSS declaration creates a layout with three columns. The first and last columns will have equal width, while the middle column will adjust its width to fit its content.
Lastly, we want the main element to start at the second column. So, we can set the `grid-column-start` property to 2.
```css
.container__center {
grid-column-start: 2;
}
```
Now, it's a breeze to move the first column to the left.
```css
.container__left {
margin-right: auto;
}
```
Finally, let's check out the demonstration to see the progress we've made so far!
```css demo.css hidden
:root {
--placeholder-size: 1rem;
}
body {
align-items: center;
display: flex;
justify-content: center;
}
.circle {
background-color: rgb(203 213 225);
border-radius: 9999px;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin-right: 0.125rem;
}
.square {
background-color: rgb(203 213 225);
border-radius: 0.25rem;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin: 0 0.125rem;
}
.container {
border: 1px solid rgb(203 213 225);
border-radius: 0.25rem;
padding: 0.5rem;
width: 16rem;
}
.container__left,
.container__center {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.container {
display: grid;
grid-template-columns: 1fr repeat(1, auto) 1fr;
}
.container__left {
margin-right: auto;
}
.container__center {
grid-column-start: 2;
}
```
```html index.html
```
Replacing the non-existing third column with the real one is a piece of cake. All you need to do is push it to the right using a single CSS declaration.
```css
.container__right {
margin-left: auto;
}
```
```css demo.css hidden
:root {
--placeholder-size: 1rem;
}
body {
align-items: center;
display: flex;
justify-content: center;
}
.circle {
background-color: rgb(203 213 225);
border-radius: 9999px;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin-right: 0.125rem;
}
.square {
background-color: rgb(203 213 225);
border-radius: 0.25rem;
height: var(--placeholder-size);
width: var(--placeholder-size);
margin: 0 0.125rem;
}
.container {
border: 1px solid rgb(203 213 225);
border-radius: 0.25rem;
padding: 0.5rem;
width: 16rem;
}
.container__left,
.container__center,
.container__right {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css hidden
.container {
display: grid;
grid-template-columns: 1fr repeat(1, auto) 1fr;
}
.container__left {
margin-right: auto;
}
.container__center {
grid-column-start: 2;
}
.container__right {
margin-left: auto;
}
```
```html index.html hidden
```
## Usages
In addition to the sample usages mentioned earlier, I've been using this technique to create a layout that centers the main content of the page while aligning the sidebar to the right side of the screen.
Here's an example of what the layout looks like:
```css demo.css hidden
.container {
border: 1px solid rgb(203 213 225);
width: 100%;
height: 16rem;
}
.container__main {
align-items: center;
display: flex;
justify-content: center;
background: rgb(203 213 225);
width: 9rem;
}
.container__sidebar {
align-items: center;
display: flex;
justify-content: center;
background: rgb(226 232 240);
width: 4rem;
}
@media (min-width: 600px) {
.container__main {
width: 15rem;
}
.container__sidebar {
width: 8rem;
}
}
```
```css styles.css
.container {
display: grid;
grid-template-columns: 1fr repeat(1, auto) 1fr;
}
.container__main {
grid-column-start: 2;
}
.container__sidebar {
margin-left: auto;
}
```
```html index.html
Main
Sidebar
```
================================================
FILE: contents/centering.mdx
================================================
---
category: Display
created: '2019-11-15'
description: Center an element with CSS flexbox
keywords: css centering, css flexbox
thumbnail: /assets/css-layout/thumbnails/centering.png
title: Centering
---
## HTML
```html index.html
```
## CSS
```css styles.css
.circular-navigation {
position: relative;
}
.circular-navigation__circle {
/* Position */
position: absolute;
top: 0;
/*
3rem is the distance from the item to the trigger element.
Replace 0deg with 60deg, 180deg, 240deg, 300deg for another item
in case you want to have a total of 6 menu items.
The formulation is 360 / numberOfItems * indexOfItem
*/
transform: rotate(0deg) translateX(-3rem);
/* Must have the same size as the trigger element */
height: 2rem;
width: 2rem;
}
.circular-navigation__content {
/*
Rotate it to make it displayed vertically
Replace -0deg with -60deg, -180deg, -240deg, -300deg for another item
in case you want to have a total of 6 menu items.
The formulation is -(360 / numberOfItems * indexOfItem)
*/
transform: rotate(-0deg);
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
/* Take full size */
height: 100%;
width: 100%;
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
.circular-navigation-container {
/* Demo */
align-items: center;
display: flex;
justify-content: center;
height: 8rem;
width: 8rem;
}
.circular-navigation {
position: relative;
height: 2rem;
width: 2rem;
}
.circular-navigation__circle {
/* Position */
position: absolute;
top: 0;
/*
3rem is the distance from the item to the trigger element.
Replace 0deg with 60deg, 180deg, 240deg, 300deg for another item
in case you want to have a total of 6 menu items.
The formulation is 360 / numberOfItems * indexOfItem
*/
transform: rotate(var(--circular-navigation__circle-degree)) translateX(-3rem);
/* Must have the same size as the trigger element */
height: 2rem;
width: 2rem;
/* Demo */
background-color: #d1d5db;
border-radius: 9999px;
}
.circular-navigation__content {
/*
Rotate it to make it displayed vertically
Replace -0deg with -60deg, -180deg, -240deg, -300deg for another item
in case you want to have a total of 6 menu items.
The formulation is -(360 / numberOfItems * indexOfItem)
*/
transform: rotate(var(--circular-navigation__content-degree));
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
/* Take full size */
height: 100%;
width: 100%;
}
.circular-navigation__circle--1 {
--circular-navigation__circle-degree: 0deg;
--circular-navigation__content-degree: -0deg;
}
.circular-navigation__circle--2 {
--circular-navigation__circle-degree: 60deg;
--circular-navigation__content-degree: -60deg;
}
.circular-navigation__circle--3 {
--circular-navigation__circle-degree: 120deg;
--circular-navigation__content-degree: -120deg;
}
.circular-navigation__circle--4 {
--circular-navigation__circle-degree: 180deg;
--circular-navigation__content-degree: -180deg;
}
.circular-navigation__circle--5 {
--circular-navigation__circle-degree: 240deg;
--circular-navigation__content-degree: -240deg;
}
.circular-navigation__circle--6 {
--circular-navigation__circle-degree: 300deg;
--circular-navigation__content-degree: -300deg;
}
```
```html index.html hidden
1
2
3
4
5
6
```
================================================
FILE: contents/close-button.mdx
================================================
---
category: Display
created: '2019-12-11'
description: Create a close button with CSS flexbox
keywords: css close button, css flexbox
thumbnail: /assets/css-layout/thumbnails/close-button.png
title: Close button
---
## HTML
```html index.html
```
## CSS
```css styles.css
.close-button {
/* Reset */
background-color: transparent;
border-color: transparent;
/* Cursor */
cursor: pointer;
/* Size */
height: 3rem;
width: 3rem;
/* Used to position the inner */
position: relative;
}
.close-button__line {
/* Background color */
background-color: #d1d5db;
/* Position */
position: absolute;
/* Size */
height: 1px;
width: 100%;
}
.close-button__line--first {
/* Position */
left: 0px;
top: 50%;
transform: translate(0%, -50%) rotate(45deg);
/* Size */
height: 1px;
width: 100%;
}
.close-button__line--second {
/* Position */
left: 50%;
top: 0px;
transform: translate(-50%, 0%) rotate(45deg);
/* Size */
height: 100%;
width: 1px;
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
.close-button {
/* Reset */
background-color: transparent;
border-color: transparent;
/* Cursor */
cursor: pointer;
/* Size */
height: 3rem;
width: 3rem;
/* Used to position the inner */
position: relative;
}
.close-button__line {
/* Background color */
background-color: #d1d5db;
/* Position */
position: absolute;
/* Size */
height: 1px;
width: 100%;
}
.close-button__line--first {
/* Position */
left: 0px;
top: 50%;
transform: translate(0%, -50%) rotate(45deg);
/* Size */
height: 1px;
width: 100%;
}
.close-button__line--second {
/* Position */
left: 50%;
top: 0px;
transform: translate(-50%, 0%) rotate(45deg);
/* Size */
height: 100%;
width: 1px;
}
```
```html index.html hidden
```
================================================
FILE: contents/color-swatch.mdx
================================================
---
category: Display
created: '2021-05-08'
description: Create a color swatch with CSS flexbox
keywords: css color swatch, css flexbox
thumbnail: /assets/css-layout/thumbnails/color-swatch.png
title: Color swatch
---
## HTML
```html index.html
```
## CSS
```css styles.css
.diagonal-section {
/* Used to position the diagonal area */
position: relative;
}
.diagonal-section__diagonal {
/* Absolute position */
left: 0px;
position: absolute;
top: 0px;
/* Take full size */
height: 100%;
width: 100%;
/* Create diagonal sides */
transform: skewY(-5deg);
/* Background color */
background-color: #d1d5db;
/* Displayed under the main content */
z-index: -1;
}
```
```css styles.css hidden
body {
height: 24rem;
}
.diagonal-section {
/* Used to position the diagonal area */
position: relative;
height: 100%;
width: 100%;
}
.diagonal-section__diagonal {
/* Absolute position */
left: 0px;
position: absolute;
top: 50%;
/* Take full size */
height: 2rem;
width: 100%;
/* Create diagonal sides */
transform: translate(0, -50%) skewY(-15deg);
/* Background color */
background-color: #d1d5db;
}
```
```html index.html hidden
```
================================================
FILE: contents/docked-at-corner.mdx
================================================
---
category: Display
created: '2019-11-23'
description: Dock an element at corner with CSS
keywords: css docked, css flexbox
thumbnail: /assets/css-layout/thumbnails/docked-at-corner.png
title: Docked at corner
---
## HTML
```html index.html
```
## See also
- Discover how to animate a docked element using the [pulse animation](https://phuoc.ng/collection/css-animation/pulse-animation/)
================================================
FILE: contents/dot-leader.mdx
================================================
---
category: Display
created: '2019-11-27'
description: Create dot leaders with CSS flexbox
keywords: css dot leader, css flexbox
thumbnail: /assets/css-layout/thumbnails/dot-leader.png
title: Dot leader
---
## HTML
```html index.html
```
## See also
- [Carousel slider](https://phuoc.ng/collection/css-layout/carousel-slider/)
================================================
FILE: contents/drawer.mdx
================================================
---
category: Navigation
created: '2019-12-13'
description: Create a drawer navigation with CSS
keywords: css drawer, css off-canvas
thumbnail: /assets/css-layout/thumbnails/drawer.png
title: Drawer
---
This pattern is also known as off-canvas.
## HTML
```html index.html
```
================================================
FILE: contents/drop-cap.mdx
================================================
---
category: Display
created: '2019-11-29'
description: Create a drop cap with CSS
keywords: css drop cap, css :first-letter
thumbnail: /assets/css-layout/thumbnails/drop-cap.png
title: Drop cap
---
## HTML
```html index.html
CSS is a style sheet language used for describing the presentation of a document written in a markup language like HTML. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.
```
================================================
FILE: contents/dropdown.mdx
================================================
---
category: Navigation
created: '2019-11-29'
description: Create a dropdown with CSS
keywords: css dropdown, css menu
thumbnail: /assets/css-layout/thumbnails/dropdown.png
title: Dropdown
---
## HTML
```html index.html
...
...
```
## CSS
```css styles.css
.dropdown {
position: relative;
}
.dropdown__trigger {
cursor: pointer;
}
/* Hide the dropdown's content by default */
.dropdown__content {
display: none;
/* Position it right below the trigger element */
left: 0;
padding-top: 0.25rem;
position: absolute;
top: 100%;
/* It should be on the top of other elements */
background-color: #fff;
z-index: 9999;
}
/* Show the content when hover on the container */
.dropdown:hover .dropdown__content {
display: block;
}
```
You can use a [triangle button](https://phuoc.ng/collection/css-layout/triangle-buttons/) to indicate that there is content under it.
Move the mouse over the button to see the dropdown.
```css placeholders.css hidden
.lines {
padding: 0.25rem 0;
width: 100%;
align-items: center;
display: flex;
justify-content: center;
flex-direction: column;
}
.line {
background: #d1d5db;
height: 1px;
margin-bottom: 0.25rem;
}
.line.line--20 {
width: 20%;
}
.line.line--40 {
width: 40%;
}
.line.line--60 {
width: 60%;
}
.line.line--80 {
width: 80%;
}
.line.line--100 {
width: 100%;
}
.rectangle {
background: #d1d5db;
border-radius: 0.25rem;
height: var(--rectangle-height);
width: var(--rectangle-width);
}
.rectangle--hor.rectangle--20 {
--rectangle-width: 20%;
}
.rectangle--hor.rectangle--40 {
--rectangle-width: 40%;
}
.rectangle--hor.rectangle--60 {
--rectangle-width: 60%;
}
.rectangle--hor.rectangle--80 {
--rectangle-width: 80%;
}
.rectangle--hor.rectangle--100 {
--rectangle-width: 100%;
}
.rectangle--hor.rectangle--sm {
--rectangle-height: 0.5rem;
}
.rectangle--hor.rectangle--md {
--rectangle-height: 2rem;
}
.rectangle--hor.rectangle--lg {
--rectangle-height: 4rem;
}
.rectangle--ver.rectangle--20 {
--rectangle-height: 20%;
}
.rectangle--ver.rectangle--40 {
--rectangle-height: 40%;
}
.rectangle--ver.rectangle--60 {
--rectangle-height: 60%;
}
.rectangle--ver.rectangle--80 {
--rectangle-height: 80%;
}
.rectangle--ver.rectangle--100 {
--rectangle-height: 100%;
}
.rectangle--ver.rectangle--sm {
--rectangle-width: 0.5rem;
}
.rectangle--ver.rectangle--md {
--rectangle-width: 2rem;
}
.rectangle--ver.rectangle--lg {
--rectangle-width: 4rem;
}
.triangle {
border-style: solid;
height: 0;
width: 0;
}
.triangle--t {
border-color: transparent transparent #d1d5db transparent;
border-width: 0 var(--triangle-size) var(--triangle-size) var(--triangle-size);
}
.triangle--r {
border-color: transparent transparent transparent #d1d5db;
border-width: var(--triangle-size) 0 var(--triangle-size) 1rem;
}
.triangle--b {
border-color: #d1d5db transparent transparent transparent;
border-width: var(--triangle-size) var(--triangle-size) 0 var(--triangle-size);
}
.triangle--l {
border-color: transparent #d1d5db transparent transparent;
border-width: var(--triangle-size) 1rem var(--triangle-size) 0;
}
.triangle--tr {
border-color: transparent #d1d5db transparent transparent;
border-width: 0 var(--triangle-size) var(--triangle-size) 0;
}
.triangle--br {
border-color: transparent transparent #d1d5db transparent;
border-width: 0 0 var(--triangle-size) var(--triangle-size);
}
.triangle--bl {
border-color: transparent transparent transparent #d1d5db;
border-width: var(--triangle-size) 0 0 var(--triangle-size);
}
.triangle--tl {
border-color: #d1d5db transparent transparent transparent;
border-width: var(--triangle-size) var(--triangle-size) 0 0;
}
.triangle--sm {
--triangle-size: 0.5rem;
}
.triangle--md {
--triangle-size: 2rem;
}
.triangle--lg {
--triangle-size: 4rem;
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
height: 24rem;
}
.dropdown {
position: relative;
/* Demo */
width: 6rem;
align-items: flex-start;
display: flex;
justify-content: center;
}
.dropdown__trigger {
cursor: pointer;
/* Demo */
border: 1px solid #d1d5db;
border-radius: 0.25rem;
height: 2rem;
width: 6rem;
padding: 0.25rem 0.5rem;
align-items: center;
display: flex;
justify-content: center;
}
/* Hide the dropdown's content by default */
.dropdown__content {
display: none;
/* Position it right below the trigger element */
left: 0;
padding-top: 0.25rem;
position: absolute;
top: 100%;
/* It should be on the top of other elements */
background-color: #fff;
z-index: 9999;
}
.dropdown__body {
/* Demo */
border: 1px solid #d1d5db;
border-radius: 0.25rem;
height: 6rem;
width: 8rem;
}
/* Show the content when hover on the container */
.dropdown:hover .dropdown__content {
display: block;
}
```
```html index.html hidden
```
================================================
FILE: contents/fading-long-section.mdx
================================================
---
category: Display
created: '2020-01-10'
description: Fading long section to indicate there is more content
keywords: css fading overflow, css linear gradient
thumbnail: /assets/css-layout/thumbnails/fading-long-section.png
title: Fading long section
---
The pattern is often used to indicate there is more content.
## HTML
```html index.html
```
================================================
FILE: contents/fixed-at-side.mdx
================================================
---
category: Display
created: '2019-12-21'
description: Fix an element at the middle of side with CSS
keywords: css fixed
thumbnail: /assets/css-layout/thumbnails/fixed-at-side.png
title: Fixed at side
---
## HTML
```html index.html
```
## See also
- [Carousel slider](https://phuoc.ng/collection/css-layout/carousel-slider/)
================================================
FILE: contents/flipping-number.mdx
================================================
---
category: Display
created: '2023-09-07'
description: Create a flipping number in CSS
keywords: css flipping number, css flipping clock, css flipping counter
openGraphCover: /og/css-layout/flipping-number.png
thumbnail: /assets/css-layout/thumbnails/flipping-number.png
title: Flipping number
---
Flipping number layout is a popular display format used in digital clocks, countdown timers, and scoreboards. It uses multiple panels to show each digit of a number, and each panel can flip over to reveal the next number, giving the impression of an analog clock face.
In web design, flip numbers are a great way to create unique and eye-catching interfaces. They're perfect for displaying all kinds of information, such as scores, prices, or countdowns.
In this post, we'll learn how to create a flipping number using CSS. Get ready to impress your users with a stunning display!
## Markup
First things first, let's prepare the layout for our flipping number. It's a simple layout that involves two elements. The container element creates the top and bottom flipping effects, while the inner element is used to display the number.
```html
42
```
## Adding effects
Instead of creating separate elements for the top and bottom backgrounds, we can simplify things by using pseudo-elements. The `::before` element can handle the top background, while the `::after` element can generate the bottom background.
To make this work, we need to position the pseudo-element absolutely within the container. We can do this by using the `position` property with different values:
```css
.flip {
overflow: hidden;
}
.flip::before {
content: '';
position: absolute;
}
```
It's important to remember that the pseudo-element won't be visible without the `content` property. In our case, the `::before` element doesn't have any content, so we can simply set the `content` property to empty.
Now, let's focus on the `::before` element, which will cover the first half of the container. We can use a combination of `top`, `left`, `height`, and `width` properties to indicate its position and dimensions:
```css
.flip::before {
top: 0;
left: 0;
height: 50%;
width: 100%;
}
```
Lastly, let's create a gradient for the top half using the `linear-gradient` function. This will allow us to set the `background` property in the following way:
```css
.flip::before {
background: linear-gradient(to right bottom, rgb(71 85 105), rgb(15 23 42));
}
```
In the code above, we're passing several parameters to the `linear-gradient` function. The first parameter, `to right bottom`, sets the direction of the gradient. In this case, it means the gradient will start at the top left and end at the bottom right.
The second and third parameters are colors that determine the start and end points of the gradient. The first color, `rgb(71 85 105)`, is a darker shade representing the starting point. The second color, `rgb(15 23 42)`, is an even darker shade representing the ending point.
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css hidden
.flip {
display: inline-flex;
padding: 1rem;
position: relative;
border-radius: 0.5rem;
overflow: hidden;
}
.flip::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(71 85 105), rgb(15 23 42));
}
.flip__number {
color: #fff;
font-size: 4rem;
font-weight: 600;
z-index: 1;
}
```
```html index.html hidden
42
```
We can use the same steps for the bottom half, with only one difference: the position and background color. Since the bottom half is positioned at the bottom, it will reset the `bottom` and `left` properties to zero.
Here's how the bottom half can be created using the `::after` pseudo-element.
```css
.flip::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(100 116 139), rgb(15 23 42));
}
```
Finally, to ensure that content is displayed on top of pseudo-elements, we need to set the `z-index` property.
```css
.flip__number {
z-index: 1;
}
```
Check out the result below.
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css hidden
.flip {
display: inline-flex;
padding: 1rem;
position: relative;
border-radius: 0.5rem;
overflow: hidden;
}
.flip::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(71 85 105), rgb(15 23 42));
}
.flip::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(100 116 139), rgb(15 23 42));
}
.flip__number {
color: #fff;
font-size: 4rem;
font-weight: 600;
z-index: 1;
}
```
```html index.html hidden
42
```
## Adding a divider
To enhance the layout's visual appeal, we can insert a thin divider between the top and bottom halves. We can achieve this by adding a border at the bottom of the first half.
```css
.flip::before {
border-bottom: 1px solid rgb(148 163 184);
}
```
As the border will occupy space, we need to slightly push up the first half to ensure both halves have the same height. We can use a negative value with the `translateY()` function to accomplish this.
```css
.flip::before {
transform: translateY(-1px);
}
```
It's important to note that the value passed must match the border's thickness. Therefore, it's better to use a CSS variable to represent the number. This way, the code will still work even if you increase the border's thickness. Plus, it'll be easier for other engineers on your team to understand, making the code easier to maintain.
```css
:root {
--divider-height: 1px;
}
.flip::before {
border-bottom: var(--divider-height) solid rgb(148 163 184);
transform: translateY(calc(-1 * var(--divider-height)));
}
```
Let's take a look at the final result we've achieved so far.
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
:root {
--divider-height: 1px;
}
.flip {
display: inline-flex;
padding: 1rem;
position: relative;
border-radius: 0.5rem;
overflow: hidden;
}
.flip::before {
content: '';
position: absolute;
top: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(71 85 105), rgb(15 23 42));
border-bottom: var(--divider-height) solid rgb(148 163 184);
transform: translateY(calc(-1 * var(--divider-height)));
}
.flip::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
height: 50%;
width: 100%;
background: linear-gradient(to right bottom, rgb(100 116 139), rgb(15 23 42));
}
.flip__number {
color: #fff;
font-size: 4rem;
font-weight: 600;
z-index: 1;
}
```
```html index.html
```
## CSS
```css styles.css
.floating-label {
border: 1px solid #d1d5db;
border-radius: 0.25rem;
position: relative;
}
.floating-label__input {
border: none;
padding: 0.5rem;
height: 100%;
}
/*
Show the label at desired position when the
placeholder of input isn't shown
*/
.floating-label__input:not(:placeholder-shown) + .floating-label__label {
background: #fff;
transform: translate(0, -200%);
opacity: 1;
}
.floating-label__label {
/* Position the label */
left: 1rem;
position: absolute;
top: 100%;
/* Hide it by default */
opacity: 0;
transition: all 200ms;
padding: 0 0.5rem;
}
```
Type something in the input to see how the label is shown up.
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
.floating-label {
border: 1px solid #d1d5db;
border-radius: 0.25rem;
position: relative;
/* Demo */
padding: 0px 1px;
height: 2.5rem;
}
.floating-label__input {
border: none;
padding: 0.5rem;
height: 100%;
}
/*
Show the label at desired position when the
placeholder of input isn't shown
*/
.floating-label__input:not(:placeholder-shown) + .floating-label__label {
background: #fff;
transform: translate(0, -200%);
opacity: 1;
}
.floating-label__label {
/* Position the label */
left: 1rem;
position: absolute;
top: 100%;
/* Hide it by default */
opacity: 0;
transition: all 200ms;
padding: 0 0.5rem;
}
```
```html index.html hidden
```
## See also
- Explore some ways to [animate a floating label](https://phuoc.ng/collection/css-animation/floating-label/).
================================================
FILE: contents/folded-corner.mdx
================================================
---
category: Display
created: '2023-09-06'
description: Create a folded corner in CSS
keywords: css folded corner
openGraphCover: /og/css-layout/folded-corner.png
thumbnail: /assets/css-layout/thumbnails/folded-corner.png
title: Folded corner
---
The folded corner layout is a popular design element in web design that adds creativity and uniqueness to a website. It creates the illusion of a folded corner on a webpage, giving it a tangible feel.
Using this technique can help highlight important information or sections on a page, making it easier for users to navigate a content-heavy website. It can also be used simply for aesthetic purposes, adding an interesting visual element to the page.
In this post, we will explore various ways to create a folded corner effect. So, get ready to learn some cool techniques!
## Markup
To begin, let's create the markup for our layout. It's as simple as adding an HTML element.
```html
```
## Using multiple backgrounds
Let's take a moment to imagine an element with a folded corner. This element is made up of two layers: a rectangle with a curved corner and a triangle placed on top of it.
To create the first layer, we can use the `linear-gradient` function to define the background of the element.
```css
background: linear-gradient(-135deg, transparent 1.7677rem, rgb(226 232 240) 0)
```
If you're not familiar with the `linear-gradient` function or the number `1.7677rem` in the sample code, don't worry. Here's what's going on:
- The `linear-gradient` function creates a gradient background for an element. The `-135deg` specifies the direction of the gradient, which in this case is from the top-right corner to the bottom-left corner.
- The first color stop in the gradient is `transparent`, which means there's no color at that point. The second color stop is `rgb(226 232 240)`, which is an RGB color value for that point in the gradient.
- The `1.7677rem` and `0` values determine where these colors are positioned within the gradient. `transparent` will be visible for the first `1.7677rem` of the gradient, followed by `rgb(226 232 240)` for the rest.
Wondering how we calculated the `1.7677rem` value? It's actually pretty simple. Just imagine that the folded corner is a square with sides of 2.5rem. But because we rotate the first stop by 135 degrees, the side of the square becomes the diagonal.
Now, a square whose diagonal is 2.5rem has a size of `2.5rem / Math.sqrt(2)`, which is `1.7677rem`. Easy, right?
Let's take a look at how it creates a curved corner:
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
.box {
height: 12rem;
width: 16rem;
background: linear-gradient(-135deg, transparent 1.7677rem, rgb(226 232 240) 0);
}
```
```html index.html
```
### Creating the triangle
There are several ways to create a triangle, such as using different border colors. However, in this section, we will stick to using the `linear-gradient` function.
```css
.triangle {
background: linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0);
}
```
In this example, we use the `to left bottom` value to specify the direction of the gradient. It starts from the top-right corner and goes to the bottom-left corner.
The first color stop is `transparent`, which means that there is no color at that point. The second color stop is `rgb(100 116 139)`, which specifies an RGB color value for that point in the gradient.
To create a diagonal line across the box from the top-right to the bottom-left corner, we start with transparency at 50% of this line and then transition into our dark color for the remaining area.
Let's take a look at how it generates a triangle shape:
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
.triangle {
height: 2.5rem;
width: 2.5rem;
background: linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0);
}
```
```html index.html
```
Next, let's move the triangle to the top-right corner of the box element. To do this, we can simply adjust the position of the background.
```css
.box {
background: linear-gradient(...) no-repeat 100% 0 / 2.5rem 2.5rem;
}
```
Let's break down the declaration into its individual parts:
- `no-repeat` is a keyword that tells the background image not to repeat.
- `100% 0` sets the position of the background image to the top-right corner of the element.
- `/ 2.5rem 2.5rem` specifies the size of the background image. The first value represents the width, and the second value represents the height. In this case, both values are set to `2.5rem`, which matches the size of our folded corner square.
Check out the box element with a triangle attached to the top-right corner. I added a simple dashed border so you can see the bounding of the box.
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
.box {
height: 12rem;
width: 16rem;
border: 2px dashed rgb(226 232 240);
background: linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0) no-repeat 100% 0 / 2.5rem 2.5rem;
}
```
```html index.html
```
### Combining backgrounds
Now that you know how to use the linear gradient to create both layers, it's time to merge them and generate the folded corner.
CSS allows us to use multiple declarations for the `background` properties by separating them with commas. Keep in mind that the order of these declarations is important and can affect the final result.
```css
.box {
background:
linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0) no-repeat 100% 0 / 2.5rem 2.5rem,
linear-gradient(-135deg, transparent 1.7677rem, rgb(226 232 240) 0);
}
```
Without further ado, let's take a look at the final result of the steps we've taken so far:
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
.box {
height: 12rem;
width: 16rem;
background:
linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0) no-repeat 100% 0 / 2.5rem 2.5rem,
linear-gradient(-135deg, transparent 1.7677rem, rgb(226 232 240) 0);
}
```
```html index.html
```
## Using a pseudo-element
In the previous section, we used a cool approach to generate a folded corner using multiple backgrounds in a single `div` element. However, this approach has some downsides. For example, it's not easy to add more styles to the triangle, like a shadow.
To add more customization to the triangle, we can use the `:after` pseudo-element to represent it. Here are some basic styles to position the triangle:
```css
.box {
position: relative;
}
.box::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 2.5rem;
height: 2.5rem;
}
```
The `position` property values of `absolute` and `relative` are applied to the box and the triangle, respectively. This ensures that the triangle is positioned absolutely within the box.
Although the triangle doesn't contain any information, we still need to set the content property to an empty `''` for it to appear. The `top` and `right` properties position the triangle in the top-right corner, while the `width` and `height` properties determine its size.
We're using a separate element to represent the triangle. This makes it easy to style it however you want. Want to add a box shadow? No problem!
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
.box {
height: 12rem;
width: 16rem;
background: linear-gradient(-135deg, transparent 1.7677rem, rgb(226 232 240) 0);
position: relative;
}
.box::after {
content: '';
position: absolute;
top: 0;
right: 0;
width: 2.5rem;
height: 2.5rem;
background: linear-gradient(to left bottom, transparent 50%, rgb(100 116 139) 0) no-repeat 100% 0;
box-shadow: -0.4rem 0.4rem 0.4rem -0.2rem rgba(0 0 0 / 50);
}
```
```html index.html
```
================================================
FILE: contents/folder-structure.mdx
================================================
---
category: Display
created: '2021-04-03'
description: Create a folder structure with CSS
keywords: css folder structure, css folder tree
thumbnail: /assets/css-layout/thumbnails/folder-structure.png
title: Folder structure
---
## HTML
```html index.html
```
================================================
FILE: contents/frame-corners.mdx
================================================
---
category: Display
created: '2023-09-06'
description: Create frame corners in CSS
keywords: css folded corner
openGraphCover: /og/css-layout/frame-corners.png
thumbnail: /assets/css-layout/thumbnails/frame-corners.png
title: Frame corners
---
The frame corner layout pattern is a popular and effective technique in web design. It uses corner elements to frame content on a web page, adding depth and structure. This technique is often used with images and shapes.
In this post, we'll teach you how to create frame corners with CSS. Are you ready to dive in and learn?
## Markup
The first step in preparing the layout is to structure it properly. This usually involves two elements: an inner element for displaying the content and an outer element that will display four frames at its corners.
Here's an example of what the layout could look like:
```html
```
## Adding overlays
Creating a frame at the corners is a simple idea. We can use CSS to add overlay elements around the content area and position them using absolute positioning.
Here's how to get started: define some CSS variables that can be reused later.
```css
:root {
--frame-border-size: 0.25rem;
--frame-height: 1rem;
--frame-width: 1rem;
}
```
The `--frame-border-size` variable controls the thickness of the frame, while `--frame-height` and `--frame-width` determine its dimensions. To create a single frame for the outer element, we can use a solid border and adjust the `padding` property to set the space between the border and the box content.
```css
.box {
border: var(--frame-border-size) solid rgb(30 41 59);
padding: var(--frame-height) var(--frame-width);
}
```
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css hidden
:root {
--frame-border-size: 0.25rem;
--frame-height: 1rem;
--frame-width: 1rem;
}
.box {
border: var(--frame-border-size) solid rgb(30 41 59);
padding: var(--frame-height) var(--frame-width);
height: 12rem;
width: 16rem;
}
.box__inner {
width: 100%;
height: 100%;
background: rgb(226 232 240);
}
```
```html index.html hidden
```
In order to hide the top and bottom borders of the box, there's a nifty trick we can use called the pseudo-element. Here's how it works:
We'll use the `::before` pseudo-element to create a vertical overlay that sits outside the box. To achieve this, we position the element absolutely within the box. We set the `position` property to both elements to make sure it stays in place.
```css
.box {
position: relative;
}
.box::before {
content: '';
position: absolute;
}
```
To create the overlay effect, we need to set the `left` and `right` properties to be the same as the frame's width, and the `top` and `bottom` properties to be the same the thickness of the frame border. By using negative numbers for these properties, we push the overlay to the outside of the box, causing the top and bottom borders to overlap.
```css
.box::before {
left: var(--frame-width);
right: var(--frame-width);
top: calc(-1 * var(--frame-border-size));
bottom: calc(-1 * var(--frame-border-size));
}
```
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css hidden
:root {
--frame-border-size: 0.25rem;
--frame-height: 1rem;
--frame-width: 1rem;
}
.box {
border: var(--frame-border-size) solid rgb(30 41 59);
padding: var(--frame-height) var(--frame-width);
height: 12rem;
width: 16rem;
position: relative;
}
.box::before {
content: '';
position: absolute;
left: var(--frame-width);
right: var(--frame-width);
top: calc(-1 * var(--frame-border-size));
bottom: calc(-1 * var(--frame-border-size));
background: rgb(226 232 240);
}
```
```html index.html hidden
```
Finally, to create the blank areas at the top and bottom, we make the top and bottom borders the same height as the frame. And voila! The top and bottom borders are hidden, and our box looks sleek and polished.
```css
.box::before {
border-top: var(--frame-height) solid #fff;
border-bottom: var(--frame-height) solid #fff;
}
```
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css hidden
:root {
--frame-border-size: 0.25rem;
--frame-height: 1rem;
--frame-width: 1rem;
}
.box {
border: var(--frame-border-size) solid rgb(30 41 59);
padding: var(--frame-height) var(--frame-width);
height: 12rem;
width: 16rem;
position: relative;
}
.box::before {
content: '';
position: absolute;
left: var(--frame-width);
right: var(--frame-width);
top: calc(-1 * var(--frame-border-size));
bottom: calc(-1 * var(--frame-border-size));
background: rgb(226 232 240);
border-top: var(--frame-height) solid #fff;
border-bottom: var(--frame-height) solid #fff;
}
```
```html index.html hidden
```
We can use the same approach and create the horizontal overlay element with the `::after` pesudo-element. Now, let's check out the final result of the steps we've followed together so far.
```css demo.css hidden
body {
display: flex;
align-items: center;
justify-content: center;
}
```
```css styles.css
:root {
--frame-border-size: 0.25rem;
--frame-height: 1rem;
--frame-width: 1rem;
}
.box {
border: var(--frame-border-size) solid rgb(30 41 59);
padding: var(--frame-height) var(--frame-width);
height: 12rem;
width: 16rem;
position: relative;
}
.box__inner {
height: 100%;
width: 100%;
background: rgb(226 232 240);
}
.box::before {
content: '';
position: absolute;
left: var(--frame-width);
right: var(--frame-width);
top: calc(-1 * var(--frame-border-size));
bottom: calc(-1 * var(--frame-border-size));
border-top: var(--frame-height) solid #fff;
border-bottom: var(--frame-height) solid #fff;
}
.box::after {
content: '';
position: absolute;
top: var(--frame-height);
bottom: var(--frame-height);
left: calc(-1 * var(--frame-border-size));
right: calc(-1 * var(--frame-border-size));
border-left: var(--frame-width) solid #fff;
border-right: var(--frame-width) solid #fff;
}
```
```html index.html
```
================================================
FILE: contents/full-background.mdx
================================================
---
category: Display
created: '2020-01-18'
description: Create a full background element with CSS
keywords: css background size cover, css full background
thumbnail: /assets/css-layout/thumbnails/full-background.png
title: Full background
---
## HTML
```html index.html
```
================================================
FILE: contents/full-screen-menu.mdx
================================================
---
category: Navigation
created: '2019-11-30'
description: Create a full screen menu with CSS flexbox
keywords: css fixed, css flexbox, css menu
thumbnail: /assets/css-layout/thumbnails/full-screen-menu.png
title: Full screen menu
---
## HTML
```html index.html
```
================================================
FILE: contents/grid-lines-background.mdx
================================================
---
category: Display
created: '2023-08-30'
description: Create a grid lines background in CSS
keywords: grid lines background, linear gradient, radial gradient
openGraphCover: /og/css-layout/grid-lines-background.png
thumbnail: /assets/css-layout/thumbnails/grid-lines-background.png
title: Grid lines background
updated: '2023-11-22'
---
Adding a grid lines background in CSS is an awesome way to give your website some visual interest and structure. This post will show you two simple ways to achieve this.
## Using background image
To create a grid pattern using CSS, you can use the `background-image` property. Start by creating a square image with two lines – one horizontal and one vertical – that intersect at the center of the square.
The image can be in either SVG or PNG format. Here's an example of a square image in SVG format:
```html index.html
```
The SVG consists of three rectangles. The first rectangle forms a white square with a size of 40 pixels. The second rectangle is 1 pixel wide and spans the full height to create a vertical line. The `x='50%'` attribute centers the line vertically.
Likewise, the last rectangle is 1 pixel high and spans the full width to create a horizontal line. It's worth noting that the last two rectangles are filled with identical colors.
Next, let's specify the `background-image` property for the element where you want the grid to show up. Simply use the `url()` function to link to your grid image file.
```css
.grid {
background-image: url('/path/to/grid.svg');
}
```
If you want the browser to avoid sending additional request to load the background image, then you can embed it like this:
```css
.grid {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Crect width='40' height='40' fill='%23fff' /%3E%3Crect x='50%' width='1' height='100%' fill='rgb(203 213 225)' /%3E%3Crect y='50%' width='100%' height='1' fill='rgb(203 213 225)' /%3E%3C/svg%3E%0A");
}
```
Voila! You now have a grid made up of horizontal and vertical lines that repeat seamlessly.
```css styles.css
.grid {
height: 16rem;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Crect width='40' height='40' fill='%23fff' /%3E%3Crect x='50%' width='1' height='100%' fill='rgb(203 213 225)' /%3E%3Crect y='50%' width='100%' height='1' fill='rgb(203 213 225)' /%3E%3C/svg%3E%0A");
}
```
```html index.html
```
By default, an image will repeat both vertically and horizontally, with each repetition being the same size as the background, which is 40 pixels in this case.
But what if you want to change the size of the repeated image? No problem! You can use the `background-size` property to customize the dimensions. For example, if you set it to 20 pixels, you'll create smaller squares instead. Here's the code you need to make it happen.
```css
.grid {
background-size: 20px;
}
```
## Using linear gradients
Another way to create grid lines in CSS is with the `linear-gradient()` function.
To make a grid, first, select the element(s) you want to add a grid background to and set the `background-image` property. Then, use the `linear-gradient()` function to specify two colors that are similar or identical, separated by a transparent section of the same width as your desired line thickness.
```css
.grid {
background-image: linear-gradient(to right, gray 1px, transparent 1px);
}
```
The code above creates gray vertical lines that are one pixel thick. You can adjust the line thickness by changing the value of `1px` in both parts of the gradient (i.e., `gray 2px`, `transparent 2px`, for two-pixel-thick lines).
To make horizontal lines, change `to right` to `to bottom`. If you want both horizontal and vertical lines, simply combine both gradients.
```css
.grid {
background-image:
linear-gradient(to right, gray 1px, transparent 1px),
linear-gradient(to bottom, gray 1px, transparent 1px);
}
```
Finally, don't forget to set the size of the squares using the `background-size` property.
To adjust the color and spacing of lines, simply change the value of `gray` to any other valid CSS color value, as shown in the example below.
```css styles.css
.grid {
height: 16rem;
background-image:
linear-gradient(to right, rgb(203 213 225) 1px, transparent 1px),
linear-gradient(to bottom, rgb(203 213 225) 1px, transparent 1px);
background-size: 2.5rem 2.5rem;
background-position: center center;
}
```
```html index.html
```
## Grid dot background
We can use a similar approach to create a grid with a dot background, but this time we'll use the `radial-gradient` function to make circles with a radius of 2 pixels. Don't hesitate to adjust the background color and radius to suit your needs.
```css styles.css
.grid {
height: 16rem;
background-image: radial-gradient(circle, rgb(203 213 225) 2px, #fff 2px);
background-size: 2.5rem 2.5rem;
background-position: center center;
}
```
```html index.html
```
## See also
- [Snap a draggable element to a grid](https://phuoc.ng/collection/react-drag-drop/snap-a-draggable-element-to-a-grid/)
================================================
FILE: contents/grid-without-double-borders.mdx
================================================
---
category: Layout
created: '2023-08-27'
description: How to create a CSS grid without double borders
keywords: css grid
openGraphCover: /og/css-layout/grid-without-double-borders.png
thumbnail: /assets/css-layout/thumbnails/grid-without-double-borders.png
title: Grid without double borders
---
CSS grids are an amazing tool for creating complex web page layouts. However, working with default styling can be a bit tricky, especially when it comes to borders. In this post, we'll show you how to create a CSS grid without double borders.
First, let's create the grid itself. To do this, we'll use the `display: grid` property.
```css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 4rem);
}
```
In this example, we've made a 3x3 grid with three columns and three rows. Each row is 4rem tall, and each column takes up an equal fraction of the available space. This means that no matter what size screen you're using, the columns will be evenly spaced.
Now that we've got the grid set up, we want to add borders to each cell. But here's the thing: CSS grids will automatically add double borders to adjacent cells. We'll be exploring some solutions to this issue in the next sections.
## Collapsing the borders
The grid looks a lot like a table, and as with tables, we face the same issue. But don't worry, there's a solution we can use: the `border-collapse` property. Let me show you an example.
```css
.grid {
border-collapse: collapse;
}
.grid__item {
border: 1px solid rgb(203 213 225);
}
```
In this example, we've set the `border-collapse` property to `collapse`. This should collapse adjacent borders into a single border, and we've also added a 1 pixel border to each cell using the `.grid__item` class. However, the approach doesn't work as expected. Unfortunately, the borders are still duplicated visually, as you can see below.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
height: 16rem;
}
```
```css styles.css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 4rem);
border-collapse: collapse;
width: 12rem;
}
.grid__item {
border: 1px solid rgb(203 213 225);
}
```
```html index.html
```
## Pairing the borders
There's an easier way to apply borders to your cells. Instead of setting the border for all four sides, we can apply it to just two. This approach is more natural and straightforward.
```css
:root {
--grid-border: 1px solid rgb(203 213 225);
}
.grid__item {
border-right: var(--grid-border);
border-bottom: var(--grid-border);
}
```
The grid will fill in the missing borders at the top and left sides.
```css
.grid {
border-top: var(--grid-border);
border-left: var(--grid-border);
}
```
And there you have it! Check it out, it works just as we expected!
> Did you notice in the sample code above, how I created a CSS variable to define the border? By using the variable in different places, we can avoid duplicating code everywhere. This is what we call **Don't Repeat Yourself** or **DRY**, and it's always a great practice to follow.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
height: 16rem;
}
```
```css styles.css
:root {
--grid-border: 1px solid rgb(203 213 225);
}
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 4rem);
border-top: var(--grid-border);
border-left: var(--grid-border);
width: 12rem;
}
.grid__item {
border-right: var(--grid-border);
border-bottom: var(--grid-border);
}
```
```html index.html
```
## Using the outline property
Another solution for styling elements is to use the CSS `outline` property. The outline creates a visual effect similar to a border, but it doesn't take up space on the target element.
```css
.grid__item {
outline: 1px solid rgb(203 213 225);
}
```
Although it's a step in the right direction, using the `outline` property alone doesn't completely solve the issue of double borders. We're still missing a small piece of the puzzle.
But don't worry, because CSS grid has a trick up its sleeve. The `grid-gap` property is here to save the day! This handy property creates space between rows and columns in a CSS grid layout. By specifying the size of the gap between each row and column, we gain more control over the spacing of elements within the grid.
```css
.grid {
grid-gap: 1px;
}
```
We can solve the issue by creating a grid with a 1px gap between each row and column, just like the outline. Here's a visual representation of how it works.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
height: 16rem;
}
```
```css styles.css
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 4rem);
grid-gap: 1px;
width: 12rem;
}
.grid__item {
outline: 1px solid rgb(203 213 225);
}
```
```html index.html
```
================================================
FILE: contents/linear-gauge.mdx
================================================
---
category: Feedback
created: '2023-11-20'
description: Create a linear gauge
openGraphCover: /og/css-layout/linear-gauge.png
thumbnail: /assets/css-layout/thumbnails/linear-gauge.png
title: Linear gauge
---
A **linear gauge** is a handy tool for displaying numerical values within a specific range. It's like a bar with markings that represent the range of values and an indicator that points to the current value. Linear gauges are great for showing progress, performance, or other quantitative metrics quickly and easily. You can use them in dashboards, reports, or presentations to help people understand complex data at a glance. They're simple and intuitive, making them an effective way to communicate important information in a clear and concise manner.
For instance, think of a fitness app that tracks your daily step count. The app could display a linear gauge that shows your progress towards your daily goal, with markings indicating the range of steps from 0 to the goal amount. As you walk throughout the day, the indicator on the gauge would move in real-time to show how many steps you've taken so far. This visualization can motivate users to reach their step goal and monitor their progress over time. Linear gauges can also be used in other contexts, such as fundraising campaigns or sales targets, to track progress towards specific goals and keep stakeholders informed.
Linear gauges are also used in real-life situations, like in modern cars with fuel economy gauges. These gauges display how efficiently the vehicle is using fuel, with markings indicating different levels of fuel efficiency. The indicator moves up or down based on how efficiently the car is being driven at any given moment, providing drivers with real-time feedback on their driving habits.
These are just a few examples of how linear gauges can be used to communicate important information quickly and effectively. In this post, we'll learn how to create a linear gauge.
## Setting up the layout
Setting up a layout for a simple linear gauge can be done with just one element that represents the progress.
```html
```
In order to position the progress indicator inside the gauge, we need to use absolute positioning. First, we set the `position` property of the gauge container to `relative`, so that any child elements with absolute positioning are positioned relative to it.
Next, we set the position property of the progress indicator to `absolute`, and give it a `top` and `left` value of 0. This will position it at the top left corner of the gauge container. Finally, we set the `width` of the progress indicator to a percentage value based on the current value being displayed. This will cause it to stretch or shrink horizontally as needed.
```css
.gauge {
position: relative;
}
.gauge__progress {
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
}
```
Setting different background colors for the gauge and progress indicator can make it easier to distinguish between the two elements, improving the gauge's readability. By using contrasting colors, we can highlight the progress indicator and make it stand out against the gauge's background. This is especially helpful when displaying data with a wide range of values or when there are multiple gauges on a single page. Moreover, choosing visually appealing colors can enhance the gauge's overall look and feel, making it more engaging for viewers to interact with.
```css
.gauge {
background: rgb(203 213 225);
}
.gauge__progress {
background: rgb(99 102 241);
}
```
Here's what the gauge looks like:
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.gauge {
position: relative;
width: 16rem;
height: 0.5rem;
background: rgb(203 213 225);
}
.gauge__progress {
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
background: rgb(99 102 241);
}
```
```html index.html
```
## Adding ticks to the linear gauge
To make your linear gauge more informative, it's important to include ticks. Ticks provide visual markers that indicate specific points on the gauge and help users understand where they are on the scale.
In this example, we add five ticks between 0 and 100 percent, representing key milestones along the way. This makes it easier for users to quickly gauge their progress and understand their current position.
```html
```
To add ticks to a gauge, we use absolute positioning and set the `left` property to a percentage value based on where we want the tick to appear. For example, to add a tick at the 25% mark, we set `left` to 25%. The tick is then positioned at that point on the gauge.
We can adjust the height of each tick using the `height` property and set the `width` to 1px to create a thin vertical line. By default, the tick color matches the gauge container, but we can customize it with CSS to create a more visually appealing and informative gauge.
By adding ticks to a gauge, we can provide viewers with additional information about the data being displayed. We can also use different colors or styles for each tick to make the gauge easier to read and interpret.
```css
.gauge__tick {
position: absolute;
top: 100%;
height: 0.5rem;
width: 1px;
background: rgb(203 213 225);
}
```
We can make our gauge even more informative by adding smaller ticks, also known as minor ticks, to the axis. We can insert three minor ticks between each major tick by placing them at a percentage value that falls between two adjacent major ticks. This provides more detailed information on the range of values displayed and helps viewers understand the gauge better.
```html
...
```
To make it easier for viewers to distinguish between major and minor ticks, we can use a separate CSS class and adjust its height to make it smaller than the main ticks. This way, viewers can understand the ticks correctly and avoid any confusion.
```css
.gauge__tick--minor {
height: 0.25rem;
}
```
Check out the demo below to see how even small changes can make a big difference with ticks.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.gauge {
position: relative;
width: 16rem;
height: 0.5rem;
background: rgb(203 213 225);
}
.gauge__progress {
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
background: rgb(99 102 241);
}
.gauge__tick {
position: absolute;
top: 100%;
height: 0.5rem;
width: 1px;
background: rgb(203 213 225);
}
.gauge__tick--minor {
height: 0.25rem;
}
```
```html index.html
```
## Enhancing the linear gauge with labels
We can make the linear gauge even more informative by adding labels to indicate specific values along the gauge. Labels can be used to show the current value of the progress indicator or to mark important milestones on the gauge.
To add a label, we simply create a new element inside the tick element, give it a class name, and set its content to the value we want to display. With this simple addition, our linear gauge becomes even more useful and visually appealing.
```html
50
...
```
In this example, we've added a label to the gauge at the 50% mark. To position the label, we use absolute positioning and set its `left` property to 50%. This centers the label horizontally within the tick element. To center the label vertically, we use the `transform` property to move it up by a quarter of the tick's height. By combining these CSS properties, we can create labels that show data in real-time and give viewers more information about the values being displayed. We can also use different colors or styles for each label to make the gauge more visually appealing and easy to read.
```css
.gauge__label {
position: absolute;
left: 50%;
transform: translate(-50%, 0.25rem);
}
```
Customizing the appearance of our labels can help make them more visually appealing for viewers. By adjusting properties like font size and color, we can create a polished and professional look for our linear gauge.
By combining ticks, labels, and other design elements, we can create a visualization that effectively communicates important information to viewers in an engaging and informative way.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.gauge {
position: relative;
width: 16rem;
height: 0.5rem;
background: rgb(203 213 225);
}
.gauge__progress {
position: absolute;
top: 0;
left: 0;
width: 60%;
height: 100%;
background: rgb(99 102 241);
}
.gauge__tick {
position: absolute;
top: 100%;
height: 0.5rem;
width: 1px;
background: rgb(203 213 225);
}
.gauge__tick--minor {
height: 0.25rem;
}
.gauge__label {
position: absolute;
left: 50%;
transform: translate(-50%, 0.5rem);
}
```
```html index.html
0
25
50
75
100
```
By changing the position from `left` to `top`, we can easily create a horizontal gauge as follows:
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.gauge {
position: relative;
height: 16rem;
width: 0.5rem;
background: rgb(203 213 225);
}
.gauge__progress {
position: absolute;
top: 0;
left: 0;
height: 60%;
width: 100%;
background: rgb(99 102 241);
}
.gauge__tick {
position: absolute;
left: 100%;
width: 0.5rem;
height: 1px;
background: rgb(203 213 225);
}
.gauge__tick--minor {
width: 0.25rem;
}
.gauge__label {
position: absolute;
left: 50%;
transform: translate(0.5rem, -50%);
}
```
```html index.html
0
25
50
75
100
```
## Conclusion
CSS and HTML give us the power to create linear gauges that are not only informative but also visually appealing. By adding ticks and labels to our gauge, we can provide more context for viewers to easily interpret the data in real-time. Customizing the colors and styles of our gauge elements can create a more engaging user experience that encourages viewers to interact with the data. Overall, CSS and HTML offer a robust toolkit for creating effective linear gauges that communicate important information clearly and concisely.
================================================
FILE: contents/lined-paper.mdx
================================================
---
category: Display
created: '2020-01-17'
description: Create lined paper with CSS
keywords: css linear gradient, css lined paper, css multiple horizontal lines
thumbnail: /assets/css-layout/thumbnails/lined-paper.png
title: Lined paper
---
## HTML
```html index.html
...
```
## CSS
```css styles.css
.lined-paper {
/* Lined background */
background-image: linear-gradient(#d1d5db 1px, transparent 0px);
background-size: 100% 2em;
/*
Display the content on top of the lines.
The line height must be the same as the background size defined above
*/
background-position-y: 1.5rem;
line-height: 2em;
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
.lined-paper {
/* Lined background */
background-image: linear-gradient(#d1d5db 1px, transparent 0px);
background-size: 100% 2em;
/*
Display the content on top of the lines.
The line height must be the same as the background size defined above
*/
background-position-y: 1.5rem;
line-height: 2em;
/* Demo */
overflow: hidden;
}
```
```html index.html hidden
Cascading Style Sheets (CSS) is a style sheet language used for describing the presentation of a document written in a markup language like HTML. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.
```
================================================
FILE: contents/mega-menu.mdx
================================================
---
category: Navigation
created: '2019-12-29'
description: Create a mega menu with CSS
keywords: css mega menu
thumbnail: /assets/css-layout/thumbnails/mega-menu.png
title: Mega menu
---
## HTML
```html index.html
```
================================================
FILE: contents/pie-chart.mdx
================================================
---
category: Feedback
created: '2023-11-17'
description: Create a pie chart
openGraphCover: /og/css-layout/pie-chart.png
thumbnail: /assets/css-layout/thumbnails/pie-chart.png
title: Pie chart
---
Pie charts are a great way to visually represent data. They show data as parts of a whole, making it easy to compare and analyze. Pie charts are especially helpful when working with percentages or proportions that add up to 100%. They can also help identify trends, patterns, and outliers in the data. By using different colors and labeling each slice, you can create a clear and easy-to-understand representation of complex information.
In this post, we'll show you how to create a pie chart using pure HTML and CSS. It's a simple yet effective way to communicate important data points to your audience. Let's get started!
## Setting up the layout
Generating a pie chart is a simple process. A pie chart is usually placed in a circle. To begin, we divide the circle into two equal halves.
```html
```
To create the chart, we rotate one half of the circle based on the percentage of progress being displayed, while the other half remains stationary as the chart's background. In the next section, we'll dive into the details of how to implement this idea.
## Positioning halves
To create a circle shape for our container, we can use the `border-radius` property and set it to 50%. This will round all four corners and voila! We have a perfect circle. Don't forget to specify the `height` and `width` of the circle to determine its size. If both values are the same, our circle will be perfectly round and symmetrical.
```css
.circle {
border-radius: 50%;
height: 12rem;
width: 12rem;
}
```
Both halves of the circle are positioned absolutely, so we need to change the `position` style to `relative`.
```css
.circle {
position: relative;
overflow: hidden;
}
```
When creating a pie chart inside a circle, it's crucial to use the `overflow: hidden` property. This ensures that any parts of the pie chart that extend beyond the bounds of the circle are hidden from view, giving the chart a professional and polished look.
To position the two halves of the circle, we use `position: absolute` in CSS. This lets us place the elements anywhere we want within their parent container. Both halves should have a height of 50% and a width of 100%, so they each occupy half of the circle.
To ensure proper positioning, we also set `transform-origin: 50% 100%;`. This ensures that when we rotate one of the halves, it rotates around its bottom center point, which is exactly what we need to create a pie chart.
```css
.circle__half {
position: absolute;
top: 0;
height: 50%;
width: 100%;
transform-origin: 50% 100%;
}
```
To give the first half of the circle a background color, we can apply a CSS style to it. This will make the portion of the chart that represents completed progress have a solid color.
```css
.circle__half--1 {
background: rgb(99 102 241);
}
```
By using positioning properties, we can easily create a pie chart. We rotate one half of the circle based on the percentage of progress being displayed, while the other half remains stationary, acting as the chart's background.
To illustrate, let's say we want to display progress by rotating the second half of the circle. In the sample code below, we rotate it by 120 degrees:
```css
.circle__half--2 {
transform: rotate(120deg);
}
```
To make the second half of the circle transparent, we need to set its `background` property to `inherit`. This is because we only want the first half of the circle to have a solid color while the second half should be see-through to show the underlying container. By setting `background: inherit`, we tell the browser to use the same background color as its parent element. This creates a smooth transition between our pie chart and its surrounding container.
```css
.circle__half--2 {
background: inherit;
}
```
Take a look at the demo below:
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.circle {
background: rgb(203 213 225);
border-radius: 50%;
position: relative;
overflow: hidden;
height: 12rem;
width: 12rem;
}
.circle__half {
position: absolute;
top: 0;
height: 50%;
width: 100%;
transform-origin: 50% 100%;
}
.circle__half--1 {
background: rgb(99 102 241);
}
.circle__half--2 {
background: inherit;
transform: rotate(120deg);
}
```
```html index.html
```
Keep in mind that if you want to display a pie chart with a degree greater than 180, the second half must have the same background color as the first half.
```css
.circle__half--2 {
background: rgb(99 102 241);
transform: rotate(60deg);
}
```
Here's an example of how to create a pie chart using 240 degrees.
```css demo.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
```
```css styles.css
.circle {
background: rgb(203 213 225);
border-radius: 50%;
position: relative;
overflow: hidden;
height: 12rem;
width: 12rem;
}
.circle__half {
position: absolute;
top: 0;
height: 50%;
width: 100%;
transform-origin: 50% 100%;
}
.circle__half--1 {
background: rgb(99 102 241);
}
.circle__half--2 {
background: rgb(99 102 241);
transform: rotate(60deg);
}
```
```html index.html
```
## Conclusion
Pie charts are an excellent way to visually represent data. They help viewers quickly and easily understand how different parts relate to the whole. With pure HTML and CSS, creating a pie chart is simple and customizable.
In this post, we'll cover the basics of creating a pie chart in CSS. You'll learn how to position the circle halves using absolute positioning and `transform-origin`. We'll also discuss setting background colors for each half and rotating one half based on the progress percentage.
By using these techniques, you can create beautiful and informative pie charts that will impress your audience. Remember to keep it simple, avoid cluttering your chart with too much information, and label each slice clearly. Use colors sparingly to ensure viewers can easily understand what they're looking at.
================================================
FILE: contents/popover-arrow.mdx
================================================
---
category: Feedback
created: '2019-12-03'
description: Create a popover arrow with CSS
keywords: css arrow, css
thumbnail: /assets/css-layout/thumbnails/popover-arrow.png
title: Popover arrow
---
## HTML
```html index.html
...
```
## CSS
```css styles.css
.popover-arrow {
/* Border */
border: 1px solid #d1d5db;
/* Used to position the arrow */
position: relative;
}
.popover-arrow__arrow {
/* Size */
height: 0.5rem;
width: 0.5rem;
background-color: #fff;
position: absolute;
}
.popover-arrow__arrow--tl {
/* Position at the top left corner */
left: 1rem;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--tc {
/* Position at the top center */
left: 50%;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--tr {
/* Position at the top right corner */
right: 1rem;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--rt {
/* Position at the right top corner */
right: 0;
top: 1rem;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, 50%) rotate(45deg);
}
.popover-arrow__arrow--rc {
/* Position at the right center */
right: 0;
top: 50%;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--rb {
/* Position at the right bottom corner */
bottom: 1rem;
right: 0;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--bl {
/* Position at the bottom left corner */
bottom: -0.5rem;
left: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--bc {
/* Position at the bottom center */
bottom: -0.5rem;
left: 50%;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--br {
/* Position at the bottom right corner */
bottom: -0.5rem;
right: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--lt {
/* Position at the left top corner */
left: 0;
top: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, 50%) rotate(45deg);
}
.popover-arrow__arrow--lc {
/* Position at the left center */
left: 0;
top: 50%;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--lb {
/* Position at the left bottom corner */
bottom: 1rem;
left: 0;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
height: 24rem;
}
.popover-arrow {
/* Border */
border: 1px solid #d1d5db;
/* Used to position the arrow */
position: relative;
/* Demo */
height: 16rem;
width: 16rem;
}
.popover-arrow__arrow {
/* Size */
height: 1rem;
width: 1rem;
background-color: #fff;
position: absolute;
}
.popover-arrow__arrow--tl {
/* Position at the top left corner */
left: 1rem;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--tc {
/* Position at the top center */
left: 50%;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--tr {
/* Position at the top right corner */
right: 1rem;
top: 0;
/* Border */
border-left: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--rt {
/* Position at the right top corner */
right: 0;
top: 1rem;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, 50%) rotate(45deg);
}
.popover-arrow__arrow--rc {
/* Position at the right center */
right: 0;
top: 50%;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--rb {
/* Position at the right bottom corner */
bottom: 1rem;
right: 0;
/* Border */
border-right: 1px solid #d1d5db;
border-top: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--bl {
/* Position at the bottom left corner */
bottom: -1rem;
left: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--bc {
/* Position at the bottom center */
bottom: -1rem;
left: 50%;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--br {
/* Position at the bottom right corner */
bottom: -1rem;
right: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-right: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--lt {
/* Position at the left top corner */
left: 0;
top: 1rem;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, 50%) rotate(45deg);
}
.popover-arrow__arrow--lc {
/* Position at the left center */
left: 0;
top: 50%;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
.popover-arrow__arrow--lb {
/* Position at the left bottom corner */
bottom: 1rem;
left: 0;
/* Border */
border-bottom: 1px solid #d1d5db;
border-left: 1px solid #d1d5db;
transform: translate(-50%, -50%) rotate(45deg);
}
```
```html index.html hidden
```
## See also
- [Speech bubble](https://phuoc.ng/collection/css-layout/speech-bubble/)
- [Triangle buttons](https://phuoc.ng/collection/css-layout/triangle-buttons/)
================================================
FILE: contents/presence-indicator.mdx
================================================
---
category: Feedback
created: '2019-11-29'
description: Create a presence indicator with CSS
keywords: css indicator
thumbnail: /assets/css-layout/thumbnails/presence-indicator.png
title: Presence indicator
---
## HTML
```html index.html
```
## See also
- [Indeterminate progress bar](https://phuoc.ng/collection/css-layout/indeterminate-progress-bar/)
================================================
FILE: contents/property-list.mdx
================================================
---
category: Display
created: '2019-11-25'
description: Create a property list with CSS flexbox
keywords: css flexbox, property list
thumbnail: /assets/css-layout/thumbnails/property-list.png
title: Property list
---
## HTML
```html index.html
```
================================================
FILE: contents/radial-progress-bar.mdx
================================================
---
category: Feedback
created: '2019-11-30'
description: Create a radial progress bar with CSS flexbox
keywords: css clip rect, css flexbox, css progress bar
thumbnail: /assets/css-layout/thumbnails/radial-progress-bar.png
title: Radial progress bar
---
## HTML
```html index.html
...
```
## CSS
```css styles.css
:root {
--radial-progress-bar-size: 8rem;
--radial-progress-bar-border-width: 0.75rem;
}
.radial-progress-bar {
position: relative;
height: var(--radial-progress-bar-size);
width: var(--radial-progress-bar-size);
}
.radial-progress-bar__percentages {
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
/* Rounded border */
border: var(--radial-progress-bar-border-width) solid #d1d5db;
border-radius: 9999px;
/* Size */
height: 100%;
width: 100%;
}
.radial-progress-bar__curve {
/* Position */
left: 0;
position: absolute;
top: 0;
/* Take full size */
height: 100%;
width: 100%;
/* If percentages is less than 50 */
/* clip: rect(
0px,
var(--radial-progress-bar-size),
var(--radial-progress-bar-size),
calc(var(--radial-progress-bar-size) * 0.5),
0px
); */
/* If percentages is greater than or equals to 50 */
clip: rect(auto, auto, auto, auto);
}
.radial-progress-bar__half {
/* Take full size */
height: 100%;
position: absolute;
width: 100%;
/*
Background color of curve.
The border width should be the same as the area showing the percentages
*/
border: var(--radial-progress-bar-border-width) solid #3b82f6;
border-radius: 9999px;
}
.radial-progress-bar__half--first {
/* Position */
clip: rect(0px, calc(var(--radial-progress-bar-size) * 0.5), var(--radial-progress-bar-size), 0px);
/* Number of percentages * 360 / 100 */
transform: rotate(270deg);
}
.radial-progress-bar__half--second {
/* Position */
clip: rect(0px, calc(var(--radial-progress-bar-size) * 0.5), var(--radial-progress-bar-size), 0px);
/* If percentages is less than 50 */
/* transform: rotate(0deg); */
/* If percentages is greater than or equals to 50 */
transform: rotate(180deg);
}
```
```css styles.css hidden
:root {
--radial-progress-bar-size: 8rem;
--radial-progress-bar-border-width: 0.75rem;
}
body {
align-items: center;
display: flex;
justify-content: center;
}
.radial-progress-bar {
position: relative;
height: var(--radial-progress-bar-size);
width: var(--radial-progress-bar-size);
}
.radial-progress-bar__percentages {
/* Center the content */
align-items: center;
display: flex;
justify-content: center;
/* Rounded border */
border: var(--radial-progress-bar-border-width) solid #d1d5db;
border-radius: 9999px;
/* Size */
height: 100%;
width: 100%;
}
.radial-progress-bar__curve {
/* Position */
left: 0;
position: absolute;
top: 0;
/* Take full size */
height: 100%;
width: 100%;
/* If percentages is less than 50 */
// clip: rect(0px, var(--radial-progress-bar-size), var(--radial-progress-bar-size), calc(var(--radial-progress-bar-size) * 0.5), 0px);
/* If percentages is greater than or equals to 50 */
clip: rect(auto, auto, auto, auto);
}
.radial-progress-bar__half {
/* Take full size */
height: 100%;
position: absolute;
width: 100%;
/*
Background color of curve.
The border width should be the same as the area showing the percentages
*/
border: var(--radial-progress-bar-border-width) solid #3b82f6;
border-radius: 9999px;
}
.radial-progress-bar__half--first {
/* Position */
clip: rect(0px, calc(var(--radial-progress-bar-size) * 0.5), var(--radial-progress-bar-size), 0px);
/* Number of percentages * 360 / 100 */
transform: rotate(270deg);
}
.radial-progress-bar__half--second {
/* Position */
clip: rect(0px, calc(var(--radial-progress-bar-size) * 0.5), var(--radial-progress-bar-size), 0px);
/* If percentages is less than 50 */
// transform: rotate(0deg);
/* If percentages is greater than or equals to 50 */
transform: rotate(180deg);
}
```
```html index.html hidden
75%
```
================================================
FILE: contents/radio-button-group.mdx
================================================
---
category: Input
created: '2019-12-01'
description: Create a radio button group with CSS flexbox
keywords: css flexbox, css radio button
thumbnail: /assets/css-layout/thumbnails/radio-button-group.png
title: Radio button group
---
## HTML
```html index.html
...
```
## CSS
```css styles.css
.radio-button-group {
display: flex;
/* Border */
border: 1px solid #d1d5db;
border-radius: 0.25rem;
height: 2rem;
}
.radio-button-group__label {
/* Center the content */
align-items: center;
display: inline-flex;
border-right: 1px solid #d1d5db;
padding: 0.5rem;
/* For not selected radio */
background-color: transparent;
color: #ccc;
}
.radio-button-group__label:last-child {
/* Remove the right border from the last label */
border-right-color: transparent;
}
.radio-button-group__label--selected {
/* For selected radio */
background-color: #3b82f6;
color: #fff;
margin-top: -1px;
margin-bottom: -1px;
}
.radio-button-group__input {
/* Hide it */
display: none;
}
```
```css styles.css hidden
body {
align-items: center;
display: flex;
justify-content: center;
}
.radio-button-group {
display: flex;
/* Border */
border: 1px solid #d1d5db;
border-radius: 0.25rem;
height: 2rem;
}
.radio-button-group__label {
/* Center the content */
align-items: center;
display: inline-flex;
border-right: 1px solid #d1d5db;
padding: 0.5rem;
/* For not selected radio */
background-color: transparent;
color: #ccc;
}
.radio-button-group__label:last-child {
/* Remove the right border from the last label */
border-right-color: transparent;
}
.radio-button-group__label--selected {
/* For selected radio */
background-color: #3b82f6;
color: #fff;
margin-top: -1px;
margin-bottom: -1px;
}
.radio-button-group__input {
/* Hide it */
display: none;
}
```
```html index.html hidden
```
================================================
FILE: contents/radio-switch.mdx
================================================
---
category: Input
created: '2019-11-24'
description: Create a radio switch with CSS flexbox
keywords: css flexbox, css radio switch, css switch
thumbnail: /assets/css-layout/thumbnails/radio-switch.png
title: Radio switch
---
## HTML
```html index.html
```
================================================
FILE: contents/speech-bubble.mdx
================================================
---
category: Display
created: '2023-08-31'
description: Create a speech bubble in CSS
keywords: css speech bubble
openGraphCover: /og/css-layout/speech-bubble.png
thumbnail: /assets/css-layout/thumbnails/speech-bubble.png
title: Speech bubble
---
Speech bubbles are a popular and effective way to show dialogue or thoughts in a visual way. You've probably seen them in comics, cartoons, ads, and social media posts. They add humor, emotion, and personality to a design while also giving context to the viewer. Plus, speech bubble layouts can make text-heavy designs more engaging by breaking them up.
In this post, we'll learn how to make a speech bubble layout using CSS. Let's get started!
## Markup
You only need to provide one element to add the speed bubble effect.
```html
```
## Adding a triangle
To create a speech bubble, we can display a triangle at the bottom-left corner of the container. Rather than adding an external element to the container, we can create the triangle using the `::before` pseudo-element. Here's an example to help you visualize it:
```css
.speech-bubble {
position: relative;
}
.speech-bubble::before {
content: '';
position: absolute;
bottom: 0;
left: -1rem;
border-width: 1rem;
border-style: solid;
border-color:
transparent transparent rgb(226 232 240) transparent;
}
```
First, we set the `position` property of the container to `relative`. This allowed us to position the triangle using absolute positioning.
But the real magic comes from the `::before` pseudo-element. We used the `content` property to add an empty string to this element. That may seem weird, but it's necessary because pseudo-elements require content to be displayed. To position the triangle where we wanted it, we used the `bottom` and `left` properties. By setting the `left` property to a negative value, we moved half of the triangle outside of the container.
Finally, we created the triangle shape by setting the `border-color` property to transparent for the top, left, and right borders. This made the perfect triangle we were looking for.
If you want to change the direction or position of the triangle, it's easy to do by following this [post](https://phuoc.ng/collection/css-layout/triangle-buttons/).
Let's take a moment to review the progress we've made with these steps.
```css demo.css hidden
.playground__root {
align-items: center;
display: flex;
justify-content: center;
height: 16rem;
}
```
```css
:root {
--speech-bubble-background: rgb(226 232 240);
--speech-bubble-arrow-size: 1rem;
}
.speech-bubble {
position: relative;
background: var(--speech-bubble-background);
border-radius: 0.25rem;
height: 4rem;
width: 12rem;
}
.speech-bubble::before {
content: '';
position: absolute;
bottom: 0;
left: calc(-1 * var(--speech-bubble-arrow-size));
border-width: var(--speech-bubble-arrow-size);
border-style: solid;
border-color: transparent transparent
var(--speech-bubble-background) transparent;
}
```
```html
```
## Using two pseudo-elements
In the previous section, we used the `::before` pseudo-element to create a triangle. Now, let's take it a step further and create two circles using the `::before` and `::after` pseudo-elements.
Take a look at the demo below to see how it looks:
```css demo.css hidden
.playground__root {
align-items: center;
display: flex;
justify-content: center;
height: 16rem;
}
```
```css
:root {
--speech-bubble-background: rgb(226 232 240);
}
.speech-bubble {
position: relative;
background: var(--speech-bubble-background);
border-radius: 9999px;
height: 4rem;
width: 12rem;
}
.speech-bubble::before,
.speech-bubble::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
border-radius: 9999px;
background: var(--speech-bubble-background);
}
.speech-bubble::before {
height: 1.5rem;
width: 1.5rem;
transform: translate(-0.5rem, 0.5rem);
}
.speech-bubble::after {
height: 0.75rem;
width: 0.75rem;
transform: translate(-1rem, 1rem);
}
```
```html
```
To achieve this, we position both pseudo-elements absolutely at the bottom-left corner of the container, just like in the previous example.
```css
.speech-bubble::before,
.speech-bubble::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
}
```
However, each of them is positioned differently by using the `transform` property. Let's take a closer look at the `transform` declaration for the `::before` pseudo-element. The first and second numbers move the element along the horizontal (X) and vertical (Y) axis, respectively.
```css
.speech-bubble::before {
transform: translate(-0.5rem, 0.5rem);
}
```
## See also
- [Popover arrow](https://phuoc.ng/collection/css-layout/popover-arrow/)
- [Typing indicator](https://phuoc.ng/collection/css-animation/typing-indicator/)
- [Triangle buttons](https://phuoc.ng/collection/css-layout/triangle-buttons/)
================================================
FILE: contents/spin-button.mdx
================================================
---
category: Input
created: '2019-11-25'
description: Create a spin button with CSS flexbox
keywords: css flexbox, css spin button
thumbnail: /assets/css-layout/thumbnails/spin-button.png
title: Spin button
---
## HTML
```html index.html