13 CSS Tricks that will give you an adrenaline rush🤯
Tags: css, beginners, webdev, productivity
Published: 2023-07-17 09:13:07

CSS is gaining powers with recent web evolution. And it is _very clever with tricks_ that were long existing or that have emerged. Perhaps tricks shared here will school you with CSS tricks from the depths you were yet to explore.<br />
Let's dive in.

![child makes small dive in sand beach](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9h0zu01b575pwsngkbz.gif)

1. ## Draw a triangle using border

    It can be an overkill to load images in cases where you need simple triangles e.g when adding an arrow pointer to a tooltip.

    Using only CSS, you can create a triangle using borders.<br />
    It is quite an old trick. Ideally, on an element with zero width and height, you set borders on it. All border colors are transparent **except** the one that will form an arrow. To create an arrow pointing upwards, for example, the bottom border is colored while the left and right are transparent. No need to include the top border. The border width determines size of the arrow:

    ```css
    .upwards-arrow {
    	width: 0;
    	height: 0;
    	border-left: 20px solid transparent;
    	border-right: 20px solid transparent;

    	border-bottom: 20px solid crimson;
    }
    ```

    This creates an arrow pointing upwards like shown below:

    ![CSS border triangle](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ae7uxue6iaxv188eka88.png)

    You can see this [codepen](https://codepen.io/chriscoyier/pen/DELgOJ) that visualizes the concept should it be tricky to create a mental picture.

2. ## Interchange background of an element

    `z-index` property arranges how an element is stacked onto other positioned elements. At times you may set a `z-index` property on a child element to be lower and it ends up hiding behind the background of its parent. To prevent this, you can cause a new [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Understanding_z-index/Stacking_context) on the parent element to prevent child elements from going behind it. One way way to create a stacking context is to use `isolation: isolate` css style declaration.<br />
    We can use this stacking context technique to create hover effect that interchanges a button's background. For example:

    ```css
    button.join-now {
    	cursor: pointer;
    	border: none;
    	outline: none;
    	padding: 10px 15px;

    	position: relative;
    	background-color: #5dbea3;
    	isolation: isolate; /* If ommitted, child pseudo element will be stacked behind */
    }

    button.join-now::before {
    	content: "";
    	position: absolute;
    	background-color: #33b249;
    	top: 0;
    	left: 100%;
    	right: 0;
    	bottom: 0;
    	transition: left 500ms ease-out;

    	z-index: -1;
    }

    button.join-now:hover::before {
    	left: 0;
    }
    ```

    The code above interchanges the background of the `button` when hovered. The background changes without interfering with the text on the foreground, as seen in the gif below:

    ![button background hover effect](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uuibp055h7w18i480kxg.gif)

3. ## Center an element

    Probably, you already know how to center an element using `display: flex;` and `display: grid;`. Yet another **unpopular** way to center an element on the x axis is to use `text-align` CSS property. This property works out of the box when centering text. To also center other elements in the DOM, a child element needs to have a display of `inline`. It could be `inline-block` or any other inline...

    ```css
    div.parent {
    	text-align: center;
    }

    div.child {
    	display: inline-block;
    }
    ```

4. ## Pill 💊 shape button

    You can make buttons that are pill-shaped by setting the border-radius of a button to be a very high value. Certainly, the border-radius should be higher than the height of the button.

    ```css
    button.btn {
    	border-radius: 80px; /* value higher than height of the button */
    	padding: 20px 30px;
    	background-color: #fdd835;
    	border: none;
    	color: black;
    	font-size: 20px;
    }
    ```

    result:

    ![pill-shaped button](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kdvdfflm53w2cxize54t.jpg)

    Height of the button may increase with design changes. Hence you will often find it convenient to set `border-radius` with a very high value so that your css keeps working regardless if the button grows.

5. ## Easily add beautiful loading indicator to your website

    As it is with developers, it is often a boring task to divert your focus to creating a beautiful loading indicator for your website. This focus is better utilized building other important parts of a project that deserve attention.

    As you are reading, odds are high you also find this an annoying hurdle. That is why i took the time to take away this hurdle away from you and prepare nicely done loading indicators packaged in a library so you can _"plug 'n play"_ from your dream project. It is a whole collection and you just need to pick the one that pulls the spark 💖 on you. Just see the simple usage of this [library](https://www.npmjs.com/package/react-loading-indicators), with the source available on [Github](https://github.com/hane-smitter/react-loading-indicator). Don't forget to leave a star ⭐.

6. ## Easy dark or light mode

    You only require a few lines of CSS to enable a dark/light mode on your website. You just need to let browsers know that your website can display correctly in system dark/light mode:

    ```css
    html {
    	color-scheme: light dark;
    }
    ```

    > **Note:** `color-scheme` property can be set on any DOM element other than `html`.

    Then set variables that control background color and text color through your website, making it even more bullet proof by checking for browser support:

    ```css
    html {
    	--bg-color: #ffffff;
    	--txt-color: #000000;
    }

    @supports (background-color: Canvas) and (color: CanvasText) {
    	:root {
    		--bg-color: Canvas;
    		--txt-color: CanvasText;
    	}
    }
    ```

    > **Note:** If you don't set `background-color` on an element, it will inherit the browser-defined system color for the dark/light theme matched. These system colors can be different between different browsers.

    Setting `background-color` explicitly can be useful in combination with `prefers-color-scheme` to give a different shade of color different from the default that the browser sets.

    Below is the dark/light mode in action. User's preference is simulated between dark and light mode.

    <figure>
    <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ctuq2pv1knqckdlzfklx.gif" alt="Default dark and light mode demo" />
    <figcaption>Website reactive to system dark/light mode</figcaption>
    </figure>

7. ## Truncate overflowing text with an ellipsis(`...`)

    This trick has been around for a while to _aesthetically trim_ long text. But you may still have missed it.<br />
    All you need is the following CSS:

    ```css
    p.intro {
    	width: 300px;
    	overflow: hidden;
    	text-overflow: ellipsis;
    	white-space: nowrap;
    }
    ```

    Just implement these rules:

    <ul>
    <li>Explicit width, so bounds for clipping will ever be reached.</li>
    <li>Browser wraps below long text that do not fit within an element's width. So you need to prevent that: <code>white-space: nowrap;</code>.</li>
    <li>Content that overflows should be clipped: <code>overflow: hidden;</code>.</li>
    <li>Pad a string with an ellipsis(<code>...</code>) when text is about to be clipped: <code>text-overflow: ellipsis;</code>.</li>
    </ul>

    Result looks like this:

    ![clipped text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/617f221bdw7fetthqszk.png)

8. ## Truncate long text to a number of lines

    This is slightly different from the trick above. This time, text is clipped limiting content to a number of lines.

    ```css
    p.intro {
    	width: 300px;
    	display: -webkit-box;
    	-webkit-box-orient: vertical;
    	-webkit-line-clamp: 3; /* Truncate when no. of lines exceed 3 */
    	overflow: hidden;
    }
    ```

    Output looks like this:

    ![Text truncated on number of lines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt1grhjkpsz26kkgh238.png)

9. ## Stop overworking yourself writing `top`, `right`, `bottom`, `left`

    When working with positioned elements, you often write code like this:

    ```css
    .some-element {
    	position: absolute;
    	top: 0;
    	left: 0;
    	right: 0;
    	bottom: 0;
    }
    ```

    This can be simplified using an `inset` propety:

    ```css
    .some-element {
    	position: absolute;
    	inset: 0;
    }
    ```

    Or if you have different values for `top`, `right`, `bottom` and `left`, you can set them respectively in the order like: `inset: -10px 0px -10px 0px`. This shorthand works the same way as margin.

10. ## Serve optimized images

    Try throttling to a slow internet in the browser Dev tools and visit a website made up of HD images like [unsplash](https://unsplash.com/). That's how to experience the pain of your website visitors trying to enjoy your high HD content from geographical areas with slow internet.<br />
    But you can provide a rescue especially with the `image-set` CSS trick.

    You can give options to a browser to let it decide the most appropriate image that suits a user's device. For instance:

    ```css
    .banner {
        background-image: url("elephant.png"),
    	background-image: -webkit-image-set(
    		url("elephant.webp") type("image/webp") 1x,
    		url("elephantHD.webp") type("image/webp") 2x,
    		url("elephant.png") type("image/png") 1x,
    		url("elephantHD.png") type("image/png") 2x
    	);
    }
    ```

    The code above will set the background image of an element.<br />
    If `-webkit-image-set` is supported, then background image will be an optimized image, i.e an image of supported MIME type and that better suits the resolution power of the user's device.<br />
    For example: Since a higher quality image is directly proportional to a larger size, a user who has a high resolution device but in a poor network, will prompt the browser to decide on serving a supported image with lower resolution. Ii is logical not to make a user wait for the HD image to load.

    > **Note:** An image that the browser decides as the best fit, is what is downloaded

11. ## Counters

    You don't have to get stuck on how the browser renders a numbered list. You can implement your own design utilizing `counters()`. Here's how:

    ```css
    ul {
    	margin: 0;
    	font-family: sans-serif;

    	/* Define & Initialize Counter */
    	counter-reset: list 0;
    }

    ul li {
    	list-style: none;
    }

    ul li:before {
    	padding: 5px;
    	margin: 0 8px 5px 0px;
    	display: inline-block;
    	background: skyblue;
    	border-radius: 50%;
    	font-weight: 100;
    	font-size: 0.75rem;

    	/* Increment counter by 1 */
    	counter-increment: list 1;
    	/* Show incremented count padded with `.` */
    	content: counter(list) ".";
    }
    ```

    Output looks like this:

    ![CSS counter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79v85kh0ddt9ednqcgox.png)

    This works for any other DOM element apart from `<ul>` and `<ol>`.

12. ## Form validation visual cues

    With only CSS, you can display helping visual cues to users regarding the validity of input entered in the forms. We can use `:valid` and `:invalid` CSS pseudo classes on form elements to apply appropriate styles when their contents validate successfully or not.

    Consider the following HTML page structure:

    ```html
    <!-- Regex in pattern attribute means input can accept `firstName Lastname` (whitespace sepearated names) -->
    <!-- And invalidates any other symbols like `*` -->
    <input
    	type="text"
    	pattern="([a-zA-Z0-9]\s?)+"
    	placeholder="Enter full name"
    	required
    />
    <span></span>
    ```

    `<span>` will be used to show validation results.

    And the CSS below styles an input regarding its validation result:

    ```css
    input + span {
    	position: relative;
    }

    input + span::before {
    	position: absolute;
    	right: -20px;
    	bottom: 0;
    }

    input:not(:placeholder-shown):invalid {
    	border: 2px solid red;
    }

    input:not(:placeholder-shown):invalid + span::before {
    	content: "✖";
    	color: red;
    }

    input:not(:placeholder-shown):valid + span::before {
    	content: "✓";
    	color: green;
    }
    ```

    So we have achieved interactivity without consulting any javascript. A full codepen implementing this technique is shown below:

    {% codepen https://codepen.io/hane-smitter/pen/wvQpvZL %}

13. ## Select text with one click

    This trick is inclined towards improving copy and paste experience for website users. Using `user-select: all`, you can enable easy text selection with one click. All text node below that element is selected.

    On the other hand, you can disable text selection with `user-select: none;`. Alternative way to disable text selection is placing text inside `content: '';` property of `::before` or `::after` CSS pseudo element.

---

Thanks for reading. See you in the next article. Follow me here on Dev to be notified.
{% user smitterhane %}

Also connect with me on [twitter](https://twitter.com/intent/user?screen_name=smitterhane).