Scratch – overflow
- Posted
24 May 2025
Continuing my incremental NetNewsWire theme build. Version 3 Scratch – text colour modes handles dark mode. This version handles some commonly wide elements that might otherwise create the need to scroll the view horizontally.
Wrapping inline urls
Long urls often appear inline in a few feeds in my list. Text without spaces does not wrap without some encouragement:
body {
overflow-wrap: anywhere;
}
Unlike hyphenation, this will only cause the text to break when the whole word won’t fit on its own line.
Font size vs device orientation
By default Safari enlarges text size when rotating your device to a landscape orientation. This maintains the font size relative to the viewport width; Effectively zooming the text size. I would rather see more text at the same size. We have other means to alter text size, but rotating my device is the only way to widen the display to better fit content.
To opt out of the default with CSS:
body {
-webkit-text-size-adjust: none;
text-size-adjust: none;
}
There is an un-prefixed version of the text-size-adjust property. At time of writing only Chromium browsers support it.
Responsive image sizing
It is so easy to take resizable images for granted. The first time I tackled responsive images in a NetNewsWire theme JavaScript was required, and I needed help to write it! Whatever old man; Show me the CSS:
img {
max-inline-size: 100%;
max-block-size: 100vh;
block-size: auto;
object-fit: contain;
object-position: left;
}
Thanks to some cleverness I learnt recently reading In Search of the Perfect Way to Layout Images in a Website, thanks Andrew Betts. This image resizing scales images horizontally and vertically to ensure they fit within the viewport.
Keeping iframes in frame
Making iframes the right size for their content, while fitting their container will remain a problem for as long as we keep using them. There is no perfect solution to a seamless fit. Sticking to the objective of the day, a max-width
will prevent an iframe with a large width
from escaping out view.
iframe {
border: none;
display: block;
max-inline-size: 100%;
}
I’ve yet to see a usefully inline iframe. Block reflects the common intent, so makes an obvious reset. Similarly dispensing with the border.
YouTube probably
Iframes could be any size. However, there is one size in particular that is quite common. In the case of most YouTube videos, we know the sizing, the aspect ratio, and the nature of the content.
Fitting the video to the available width whilst maintaining a relative height is not complicated:
iframe[width="560"][height="315"] {
inline-size: 100%;
block-size: auto;
aspect-ratio: 16 / 9;
}
Using this for a bit I stumbled upon a few other sizes of the same ratio. Including no size at all. Iframes are used for more than video, and videos come in more aspect ratios, but 16:9 is the most likely.
iframe:not([width][height]),
iframe[width="200"][height="113"],
iframe[width="480"][height="270"],
iframe[width="560"][height="315"],
iframe[width="1080"][height="608"] {
inline-size: 100%;
block-size: auto;
aspect-ratio: 16 / 9;
}
Scaling video
The <video>
element, like <img>
, loads with an intrinsic aspect-ratio which simplifies scaling it to fit:
video {
display: block;
inline-size: 100%;
block-size: auto;
}
Scalable Vector Graphics
Similar to iframes, SVG could be any size – anywhere between tiny character sized icons and page spanning diagrams. Step one is to prevent a large from SVG causing a side scroll:
svg {
max-inline-size: 100%;
}
How the resized SVG will scale will depend on the configuration of the SVG in question. If it has a viewBox
defined there is a chance it will have an intrinsic aspect ratio:
svg:where([viewBox]) {
display: block;
inline-size: 100%;
block-size: auto;
}
This will make the vector image fill the available width. The :where()
is useful to keep the specificity low, as I want to override this style without a selector arms race.
SVG icons
Most SVG images I encounter in blog posts are weeny little icons. To keep them that way, I’ve picked out a few common indicators that they are indeed intended to be small and overridden the above style to keep them text sized:
:is(h1,h2,h3,h4,h5,h6) a svg,
svg:not([width]),
svg:has(+ :is(a, span)) {
display: inline-block;
inline-size: 1cap;
block-size: 1cap;
margin-inline-end: 0.5ch;
}
One last SVG touch for today. Ensuring a common configuration of inline icons that are intended to inherit the text colour do so:
svg:not([fill="none"]) {
fill: currentColor;
}
Despite temptation, I’m consciously avoiding using classes used in particular blog engines. Those templates are moving targets I don’t want to chase.
Unwanted style
Instances of style=""
in feed content often introduce spacing or sizing that gets in the way of theming. I noticed the disruptive styles are most often applied to otherwise inconsequential <span>
or <div>
tags, so I’m applying the nuclear option to remove them:
.articleBody {
span,
div {
all: revert !important;
}
}
I’ve seen the odd empty div used for decorative purposes. Hiding those thus:
div:empty {
display: none;
}
Some polish
After a little more time looking at the last version, I bumped down the previously defined contrast between links and text.
Install
To enable a quick switch between different versions of this theme I’ve generated a zip of each version – incorporating the version number in the name:
Get the latest version on the Scratch project page.
Next up
There’s a possible cause of side scroll I have neglected. Tables. Maybe I’ll tackle those next, we’ll see.