Skip to content

Commit e6ca0f3

Browse files
committed
Add note about right padding when child overflows
- Add support for diff notation in code blocks - Allow long inline links in articles to break - Add Inter 700 font for strong elements - Other minor fixes, tweaks, and refactorings
1 parent 460f54c commit e6ca0f3

11 files changed

Lines changed: 308 additions & 55 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ My personal website, built with [Astro](https://astro.build) and deployed on [Gi
44

55
## Third-party assets and attributions
66

7-
- [Inter](https://rsms.me/inter) ([1](public/fonts/inter-v13-latin-400.woff2)) is licensed under the [SIL Open Font License (OFL)](https://github.com/rsms/inter/blob/master/LICENSE.txt).
7+
- [Inter](https://rsms.me/inter) ([1](public/fonts/inter-v13-latin-400.woff2), [2](public/fonts/inter-v13-latin-700.woff2)) is licensed under the [SIL Open Font License (OFL)](https://github.com/rsms/inter/blob/master/LICENSE.txt).
88
- [Raleway](https://github.com/impallari/Raleway) ([1](public/fonts/raleway-v29-latin-500.woff2), [2](public/fonts/raleway-v29-latin-600.woff2)) is licensed under the [SIL Open Font License (OFL)](https://github.com/impallari/Raleway/blob/master/OFL.txt).
99
- [Kode Mono](https://kodemono.com) ([1](public/fonts/kode-mono-v2-latin-400.woff2)) is licensed under the [SIL Open Font License (OFL)](https://github.com/isaozler/kode-mono/blob/main/OFL.txt).
1010
- [`avatar.png`](src/assets/avatar.png) was created by [Marga Hernandez](https://margahernandez.framer.website).

astro.config.ts

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { RehypePlugin } from "@astrojs/markdown-remark";
22
import type { AstroIntegration, AstroUserConfig } from "astro";
33
import type { Options as AutolinkHeadingsOptions } from "rehype-autolink-headings";
44
import type { Options as ClassNamesOptions } from "rehype-class-names";
5+
import type { Options as ExternalLinksOptions } from "rehype-external-links";
56
import type {
67
LegacyAsyncImporter,
78
LegacySharedOptions,
@@ -21,13 +22,15 @@ import mdx from "@astrojs/mdx";
2122
// @ts-expect-error - There's no type declaration but it exists.
2223
import remarkA11yEmoji from "@fec/remark-a11y-emoji";
2324
import { addExtension, createFilter, dataToEsm } from "@rollup/pluginutils";
25+
import { transformerNotationDiff } from "@shikijs/transformers";
2426
import compress from "astro-compress";
2527
import { walk } from "estree-walker";
2628
import findCacheDirectory from "find-cache-dir";
2729
import gifsicle from "gifsicle";
2830
import { customAlphabet } from "nanoid";
2931
import rehypeAutolinkHeadings from "rehype-autolink-headings";
3032
import rehypeClassNames from "rehype-class-names";
33+
import rehypeExternalLinks from "rehype-external-links";
3134
import sharp from "sharp";
3235
sharp.cache(false);
3336

@@ -37,6 +40,9 @@ sharp.cache(false);
3740

3841
const classNamesTransformer: ShikiTransformer = {
3942
name: "class-names",
43+
pre(node) {
44+
node.properties.class = "block-code-wrapper";
45+
},
4046
code(node) {
4147
node.properties.class = "block-code";
4248
},
@@ -51,12 +57,12 @@ const classNamesPlugin: [RehypePlugin, ClassNamesOptions] = [
5157
rehypeClassNames,
5258
{ ":not(pre) > code": "inline-code" }
5359
];
60+
const diffNotationTransformer = transformerNotationDiff({
61+
classActivePre: "",
62+
classLineAdd: "diff insert",
63+
classLineRemove: "diff delete"
64+
});
5465

55-
// Workaround since 'shikiConfig' does not support 'defaultColor' and
56-
// 'cssVariablePrefix' options yet. This manually does what happens when
57-
// 'defaultColor' is set to 'false' and 'cssVariablePrefix' is set to
58-
// '--c-code-'.
59-
// https://github.com/withastro/astro/issues/11238#issuecomment-2165715631
6066
function replaceShikiProperty(
6167
style: string,
6268
property: "background-color" | "--shiki-dark-bg" | "color" | "--shiki-dark"
@@ -87,6 +93,15 @@ function replaceShikiProperty(
8793

8894
return style.replace(regex, `${variableName}:${hex}`);
8995
}
96+
/**
97+
* Workaround since 'shikiConfig' does not support 'defaultColor' and
98+
* 'cssVariablePrefix' options yet. This manually does what happens when
99+
* 'defaultColor' is set to 'false' and 'cssVariablePrefix' is set to
100+
* '--c-code-'.
101+
*
102+
* @see
103+
* {@link https://github.com/withastro/astro/issues/11238#issuecomment-2165715631}
104+
*/
90105
const themeTransformer: ShikiTransformer = {
91106
name: "theme",
92107
pre(node) {
@@ -114,6 +129,28 @@ const autolinkHeadingsPlugin: [RehypePlugin, AutolinkHeadingsOptions] = [
114129
{ behavior: "wrap" }
115130
];
116131

132+
/**
133+
* Hijacks rehype-external-links to add classes to links whose href value
134+
* matches its text content instead of adding rel and target attributes.
135+
*/
136+
const externalLinksPlugin: [RehypePlugin, ExternalLinksOptions] = [
137+
rehypeExternalLinks,
138+
{
139+
rel: [],
140+
test: (element) => {
141+
if (
142+
element.children[0]?.type === "text" &&
143+
element.properties.href === element.children[0].value
144+
) {
145+
return true;
146+
}
147+
148+
return false;
149+
},
150+
properties: { class: "word-break-all" }
151+
}
152+
];
153+
117154
//==================================================
118155
// Astro - Integrations
119156
//==================================================
@@ -410,10 +447,19 @@ export default <AstroUserConfig>{
410447
smartypants: false,
411448
shikiConfig: {
412449
themes: { light: "slack-ochin", dark: "slack-dark" },
413-
transformers: [classNamesTransformer, themeTransformer]
450+
transformers: [
451+
classNamesTransformer,
452+
diffNotationTransformer,
453+
themeTransformer
454+
]
414455
},
415456
remarkPlugins: [remarkA11yEmoji],
416-
rehypePlugins: [classNamesPlugin, rehypeHeadingIds, autolinkHeadingsPlugin]
457+
rehypePlugins: [
458+
classNamesPlugin,
459+
rehypeHeadingIds,
460+
autolinkHeadingsPlugin,
461+
externalLinksPlugin
462+
]
417463
},
418464
integrations: [mdx(), optimizeImagesIntegration, compress({ Image: false })],
419465
vite: { css: { preprocessorOptions: { scss } }, plugins: [generateIdsPlugin] }

package-lock.json

Lines changed: 51 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"@astrojs/mdx": "^3.1.1",
1010
"@fec/remark-a11y-emoji": "^4.0.2",
1111
"@rollup/pluginutils": "^5.0.2",
12+
"@shikijs/transformers": "^1.10.1",
1213
"@types/gifsicle": "^5.2.0",
1314
"@types/node": "^20.2.3",
1415
"astro": "^4.5.6",
@@ -19,6 +20,7 @@
1920
"nanoid": "^5.0.6",
2021
"rehype-autolink-headings": "^7.1.0",
2122
"rehype-class-names": "^2.0.0",
23+
"rehype-external-links": "^3.0.0",
2224
"sass": "^1.62.1",
2325
"sharp": "^0.33.2"
2426
}
22.4 KB
Binary file not shown.

src/components/page/fonts.astro

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@
2121
font-display: swap;
2222
src: url("/fonts/inter-v13-latin-400.woff2") format("woff2");
2323
}
24+
@font-face {
25+
font-family: "Inter";
26+
font-style: normal;
27+
font-weight: 700;
28+
font-display: swap;
29+
src: url("/fonts/inter-v13-latin-700.woff2") format("woff2");
30+
}
2431
@font-face {
2532
font-family: "Raleway";
2633
font-style: normal;
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
---
2+
title: "What Do: Right Padding Doesn’t Apply to Overflowing Child"
3+
dateCreated: 2024-07-17
4+
dateUpdated: 2024-07-17
5+
---
6+
7+
Given this HTML:
8+
9+
```html
10+
<div id="parent">
11+
<div id="child">Some overflowing content...</div>
12+
</div>
13+
```
14+
15+
And this CSS:
16+
17+
```css
18+
#parent {
19+
height: 200px;
20+
width: 200px;
21+
padding: 20px;
22+
background: green;
23+
overflow-x: auto;
24+
}
25+
#child {
26+
width: 500px;
27+
background: greenyellow;
28+
}
29+
```
30+
31+
You'd think that there would be 20 pixels of space on all sides between `#parent` and `#child` from the set padding. For some browsers and contexts that's correct, but for others, there won't be 20 pixels of space on the right side when you scroll to show the end of `#child`.
32+
33+
What do if you want that right spacing for all browsers and contexts?
34+
35+
Instead of putting padding on `#parent`, put margin on `#child`:
36+
37+
```css
38+
#parent {
39+
height: 200px;
40+
width: 200px;
41+
padding: 20px; // [!code --]
42+
background: green;
43+
overflow-x: auto;
44+
}
45+
#child {
46+
display: inline-block; // [!code ++]
47+
width: 500px;
48+
margin: 20px; // [!code ++]
49+
background: greenyellow;
50+
}
51+
```
52+
53+
**Note:** Setting `display` to `inline-block` on `#child` is important for the spacing to apply properly.
54+
55+
## Additional Information
56+
57+
I played around with different browsers and situations to test when the right spacing does and does not get applied when setting padding on `#parent`. I used Brave on Linux to represent Blink-based browsers, Safari on iOS to represent WebKit-based browsers, and Firefox on Linux to represent Gecko-based browsers because those are what I have available.
58+
59+
From this, I found that the right spacing is always applied on Blink-based browsers (e.g., Chrome, Edge). For WebKit-based browsers, it only gets applied if `#parent` is a `pre` element and `#child` is one of `code`, `samp`, or `kbd`. Lastly, when it comes to Gecko-based browsers, the right spacing never gets applied.
60+
61+
Why is there such a stark difference in the behavior of these browsers and engines?
62+
63+
Well, perusing through the CSS 2.1 spec as well as some Working Drafts, and by perusing of course, I mean just Ctrl+F-ing my way through them, I couldn't find a specific answer as to how to handle the situation that I've outlined so far. Maybe I just missed or misconstrued something since I don't usually read specs, but the closest thing I found to an answer is the start of the description of how `overflow: scroll` should work:
64+
65+
> This value indicates that the content is clipped to the padding box, but can be scrolled into view (and therefore the box is a scroll container).
66+
67+
And this part about how overflow scrolling should work:
68+
69+
> CSS also allows a box to be scroll container that allows the user to scroll clipped parts of its scrollable overflow area into view. The visual viewport of a scroll container (through which the scrollable overflow area can be viewed) coincides with its padding box, and is called the scrollport.
70+
71+
The way I understand it is that when a child overflows its parent and the parent is allowed to scroll to show the rest of the child, the space that's allotted for viewing that content is until the parent's padding. Notice, however, that no instruction is given on whether the right padding should be visible to the user if the end of a horizontally overflowing child is shown through scrolling. This probably left vendors to decide for themselves on how to handle that situation. Hence, the difference in behavior from browser to browser.
72+
73+
I must note though that there is also no instruction as to what to do with a parent's bottom padding when a child is vertically overflowing. However, this problem doesn't arise there. The parent's bottom padding is always visible across the browsers I tested when showing the end of a vertically overflowing child by scrolling the parent.
74+
75+
Another thing to note is that the right padding is always visible when the parent's `display` is `grid` or when it's set to `flex` and its main axis is set vertically with `flex-direction` having either `column` or `column-reverse` as its value. This might be due to the changes to the inner display type these `display` values set. It may also be connected to this clause under what constitutes a scrollable overflow area:
76+
77+
> Additional padding added to the end-side of the scrollable overflow rectangle as necessary to enable a scroll position that satisfies the requirements of place-content: end alignment.
78+
79+
And this note about padding when a grid container is also a scroll container:
80+
81+
> Beware the interaction with padding when the grid container is a scroll container: additional padding is defined to be added to the scrollable overflow rectangle as needed to enable place-content: end alignment of scrollable content.
82+
83+
## Thoughts
84+
85+
Browser interoperability has come a long way from the Internet Explorer days, but it's interesting to see these little peculiarities where browsers still differ in behavior. Maybe it's because this problem has existed for a long time before even Flexbox and Grid were a thing, that they just end up not being addressed (or maybe because it's not really worth caring about).
86+
87+
It would certainly be interesting to look at browser code to see if there's a reason why they implemented things the way they did, but I neither have the time nor the C++ knowledge to do that. So I'll leave it as is with my half-baked "research".
88+
89+
Why did I do this? What's the use of this? Is it worth thinking about all this just for some spacing? Well, not really. Even if you don't use the workaround stated, you'll still be fine. Chromium-based browsers have around 70% market share, so the problem doesn't exist for all of those people. If you're just showing some code with `pre` and `code` elements like me, there's also no problem for the Safari people either, bringing your support to like 90%. As for the rest, how many will even care for that right spacing 🤷‍♂️? Nonetheless, I enjoy exploring these little browser quirks from time to time and implementing workarounds for them in my sites when I remember them.
90+
91+
## References
92+
93+
- <https://stackoverflow.com/a/10055302>
94+
- <https://www.brunildo.org/test/overscrollback.html>
95+
- <https://www.w3.org/TR/2011/REC-CSS2-20110607/visufx.html>
96+
- <https://www.w3.org/TR/CSS22/visufx.html>
97+
- <https://www.w3.org/TR/css-overflow-3>
98+
- <https://www.w3.org/TR/css-box-3>
99+
- <https://www.w3.org/TR/css-grid-1>

0 commit comments

Comments
 (0)