Skip to content

Add CSS Calc Article And Fix Slots #41

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/scheduleMerge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ jobs:
merge_schedule:
runs-on: ubuntu-latest
steps:
- uses: gr2m/merge-schedule-action@v1
- uses: gr2m/merge-schedule-action@v2
with:
time_zone: "America/Chicago"
time_zone: "America/Chicago"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
85 changes: 85 additions & 0 deletions src/blogComponents/cssCalcSize/CalcSizeAccordion.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
const {
isCalcSize,
body = "Lorem ipsum dolor sit amet consectetur adipisicing elit. Impedit in libero odit, dignissimos corrupti dolore voluptatibus praesentium sapiente corporis nam aspernatur consequuntur reprehenderit dolorem voluptate! Soluta, perferendis nam quibusdam sunt culpa eius id voluptate iste dolor eaque odio, recusandae velit nemo corrupti reprehenderit? Ex deleniti deserunt fugiat velit repellat corporis. Ex deleniti deserunt fugiat velit repellat corporis.",
header = isCalcSize ? "Using calc-size()" : "Normal expansion",
buttonText = isCalcSize ? "Expand calc-size()" : "Expand normal",
} = Astro.props
---

<div class="container">
<button data-css-calc-accordion-btn class="btn">{buttonText}</button>
<div class="card">
<div class="card-header">{header}</div>
<div class={`card-body ${isCalcSize ? "calc-size" : ""}`}>{body}</div>
</div>
</div>

<style>
.btn {
border: none;
border-radius: 0.25em;
padding: 0.5em 0.75em;
font-size: inherit;
background: var(--theme-purple);
cursor: pointer;
}

.btn:hover {
background: var(--theme-purple-hover);
}

.card {
border: 1px solid var(--theme-text);
border-radius: 0.5rem;
margin-top: 1rem;
padding: 1rem;
}

.card-body {
height: 0;
font-size: 0.85rem;
overflow: hidden;
transition: height 0.3s ease-in-out;
}

.card-body.expand {
height: auto;
}

.card-body.expand.calc-size {
height: var(--height);
height: calc-size(auto);
}
</style>

<script>
const buttons = document.querySelectorAll("[data-css-calc-accordion-btn]")

buttons.forEach(button => {
button.addEventListener("click", () => {
const body = button.closest(".container").querySelector(".card-body")

if (body.classList.contains("calc-size")) {
;(body as HTMLElement).style.setProperty(
"--height",
body.scrollHeight + "px"
)
}

body.classList.toggle("expand")
})
})

window.addEventListener("resize", () => {
const bodies = document.querySelectorAll(".card-body.calc-size")

bodies.forEach(body => {
;(body as HTMLElement).style.setProperty("--height", "auto")
;(body as HTMLElement).style.setProperty(
"--height",
body.scrollHeight + "px"
)
})
})
</script>
22 changes: 22 additions & 0 deletions src/blogComponents/cssCalcSize/CalcSizeComparison.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
import CalcSizeAccordion from "./CalcSizeAccordion.astro"
---

<div class="container">
<CalcSizeAccordion />
<CalcSizeAccordion isCalcSize />
</div>

<style>
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 2rem;
padding: 1rem 0;

@media (max-width: 40em) {
grid-template-columns: 1fr;
grid-gap: 1rem;
}
}
</style>
6 changes: 3 additions & 3 deletions src/blogComponents/cssPseudoElements/FirstLetter.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<p class="first-letter">
<div class="first-letter">
<slot />
</p>
</div>

<style>
.first-letter::first-letter {
font-size: 2em;
color: var(--theme-red);
font-weight: bold;
}
</style>
</style>
6 changes: 3 additions & 3 deletions src/blogComponents/cssPseudoElements/FirstLine.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<p class="first-line">
<div class="first-line">
<slot />
</p>
</div>

<style>
.first-line::first-line {
color: var(--theme-red);
}
</style>
</style>
10 changes: 5 additions & 5 deletions src/blogComponents/cssPseudoElements/Selection.astro
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<p class="selection">
<div class="selection" data-pseudo-element-page>
<slot />
</p>
</div>

<style>
.selection::selection {
<style is:global>
[data-pseudo-element-page].selection ::selection {
background-color: var(--theme-red);
color: white;
}
</style>
</style>
11 changes: 0 additions & 11 deletions src/blogComponents/cssPseudoElements/firstLetter.astro

This file was deleted.

9 changes: 0 additions & 9 deletions src/blogComponents/cssPseudoElements/firstLine.astro

This file was deleted.

10 changes: 0 additions & 10 deletions src/blogComponents/cssPseudoElements/selection.astro

This file was deleted.

22 changes: 0 additions & 22 deletions src/blogComponents/cssPseudoElements/tooltip.astro

This file was deleted.

10 changes: 5 additions & 5 deletions src/blogComponents/cssRangeEasterEgg/CSSRangeEasterEgg.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<p>
<div class="easter-egg" data-css-media-range-page>
<slot />
</p>
</div>

<style>
<style is:global>
@media (999px <= width < 1000px) {
p {
[data-css-media-range-page].easter-egg * {
color: var(--theme-red) !important;
}
}
</style>
</style>
4 changes: 2 additions & 2 deletions src/blogComponents/lib/Tangent.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<aside class="tangent">
<aside class="tangent" data-tangent-component>
<slot />
</aside>

Expand All @@ -14,7 +14,7 @@
color: var(--theme-text-light);
}

:global(.tangent code) {
:global([data-tangent-component].tangent code) {
background-color: var(--theme-tangent-code-inline-bg);
}
</style>
108 changes: 108 additions & 0 deletions src/pages/2024-07/css-calc-size/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
layout: "@layouts/BlogPost.astro"
title: "We Can Finally Animate height: auto; in CSS!"
date: "2024-07-01"
description: "For decades, height: auto; has been a pain to animate in CSS. But with the introduction of the calc-size() function in CSS, we can finally animate height: auto; without the need for any JavaScript."
tags: ["CSS"]
---

import CalcSizeComparison from "@blogComponents/cssCalcSize/CalcSizeComparison.astro"

## Introduction

Animating `height: auto;` in CSS seems like it should be easy, but CSS is unable to animate to/from `height: auto;` since it needs a specific height value to run any animation/transition. This has been a pain point for web developers for decades, and the only way to animate `height: auto;` was to use JavaScript to calculate the height of the element and then animate it. This is obviously not ideal, which is why CSS has finally added the brand new `calc-size()` function which makes this type of animation trivial.

## `calc-size()`

The `calc-size()` function works exactly the same as the `calc()` function, but it has the additional capability of calculating based on sizes that are automatically calculated by the browser. These values are:

1. `auto`
2. `min-content`
3. `max-content`
4. `fit-content`
5. `stretch`
6. `contain`

Essentially, what this function does is convert values like `auto` to specific pixel values which it can then use in calculations with other values. This is handy on its own, but where it is most useful is with animating elements that are `auto` sized.

```css {8}
.element {
height: 0;
overflow: hidden;
transition: height 0.3s;
}

.element.open {
height: calc-size(auto);
}
```

By wrapping our `auto` value in the `calc-size()` function, we can now animate the height of the element from `0` to `auto` without any JavaScript. Here is an example of what this looks like in practice:

<CalcSizeComparison />

The only thing you need to be away of is that you cannot animate between two automatically calculated values, such as `auto` and `min-content`.

Another interesting thing about `calc-size()` is you can actually use it on the non-automatic value in the animation and it will still animate correctly. As long as you have `calc-size` on one of the values in the animation, it will work.

```css {3}
.element {
/* This still works */
height: calc-size(0px);
overflow: hidden;
transition: height 0.3s;
}

.element.open {
height: auto;
}
```

### Doing Actual Calculations

By far the most common use for this will be with animations/transitions as shown above, but since this function works just like `calc` it can actually be used to do certain calculations that used to be impossible.

```css
.element {
width: calc-size(min-content, size + 50px);
}
```

The above CSS will set the width of the element to the minimum content size plus `50px`. The syntax for this is a bit confusing so let me explain.

`calc-size` takes two arguments, the first is the size that you want to calculate, and the second is the calculation you want to perform. In this case, we are calculating the `min-content` size of the element and then adding `50px` to that value. The keyword `size` is always used to represent the current size of the first property passed to `calc-size`. This means in our example `size` would be equal to the `min-content` size of the element.

You can even nest multiple `calc-size` functions to perform more complex calculations.

```css
.element {
width: calc-size(calc-size(min-content, size + 50px), size * 2);
}
```

This will calculate the `min-content` size of the element, add `50px` to that value, and then multiply the result by `2`.

## Browser Support

This is where we get to the bad news. As of writing this article, `calc-size()` is only supported in Chrome Canary when the `#enable-experimental-web-platform-features` flag is enabled. It is so new there isn't even a caniuse.com page for me to link to yet.

Luckily, this CSS feature is not something that will break your site if it isn't supported. It will just mean that the animation won't work, so you can use it today and it will act as a progressive enhancement for users on browsers that support it.

```css {8-9}
.element {
height: 0;
overflow: hidden;
transition: height 0.3s;
}

.element.open {
height: auto;
height: calc-size(auto);
}
```

With the above CSS the animation will work in browsers that support `calc-size()` while in older browsers it will just show the element without any animation.

## Conclusion

`calc-size()` is a fantastic new addition to CSS that will make animating `auto` based sizes incredibly easy. It also opens up a lot of possibilities for doing calculations that were previously impossible in CSS. I can't wait for this feature to be supported in all browsers!
Loading