Skip to main content

Some Imaginary CSS

By Tyler Sticka

Published on January 22nd, 2020

Topics

The other day I was using CSS grid and custom properties to solve some problems that would have seemed almost impossible only a year or two ago. This made me wonder: What CSS could I be writing in a few years that might seem far-fetched today?

Just for fun, I went through some of my recent CSS files and re-wrote portions using fictional CSS features I wish existed. Then I asked a few of my capable Cloud Four crew to help me illustrate some of those ideas.

As far as I know, none of these examples are real as of this writing… they are purely flights of fancy!

This is the most requested missing CSS feature, and I continue to find use cases with each and every project. Here’s a simple one: Only round an element’s corners when it’s narrower than the full viewport width.

.card:media(width < 100vw) {
  border-radius: 0.5em;
}Code language: CSS (css)
A wide viewport with rounded cards beside a narrower viewport with full-width, non-rounded cards
Illustration by Paul Hebert

Plugins like PostCSS Inline SVG have made me pine for a future where SVG is as much a first-class citizen of our presentation as it is our content.

@svg icon-star {
  content: url("/icons/star.svg");
  stroke: currentColor;
  stroke-width: 0.125em;
}

.icon-star {
  background-image: icon-star;
}Code language: CSS (css)

vertical-align: middle aligns an element with the baseline of text minus half its x-height. This makes it a poor fit for glyph-sized elements like icons, which will always look a tad too low. Ideally we’d have a property that would align with the middle of the typeface’s cap height instead.

.icon {
  vertical-align: text-middle;
}Code language: CSS (css)
The text 'Favorite' accompanied by a heart icon repeated twice, the first aligned with the x-height, the second with the cap height

It’s easy to make child elements scroll independently of the document. But it would be nice to easily allow “fullscreen” elements like modals and menus to take over as the document’s primary scrolling element.

.menu.is-open {
  overflow: document;
}Code language: CSS (css)

Making elements large enough for our fingers can be more challenging than it seems. It’d be swell if we could manipulate the interactive area via CSS!

.button {
  pointer-box-offset: 0.5rem;
}Code language: CSS (css)
A touch target extends past the visual boundaries of a button element within a web page
Illustration by Danielle Romo

Horizontal navigation patterns like breadcrumbs often include visual separators between each segment. While there are several ways to style these separators via CSS (using pseudo elements and adjacent sibling selectors, for example), a surprising number of websites still hard-code vertical bars or other text characters right in their HTML.

Maybe what we need is a simpler way to inject content between adjacent elements instead of just before or after?

.breadcrumbs > *::between {
  content: "▸";
  margin: 0 2ch;
}Code language: CSS (css)
Breadcrumb navigation with small arrows between each link
Illustration by Danielle Romo

It feels a little silly that we can’t just override <select> arrows and similar details without obliterating them entirely.

select::expand {
  content: url("icons/arrow-down.svg");
}Code language: CSS (css)
A mosaic of various styled select dropdown arrows
Illustration by Paul Hebert

Something I always miss from my graphic design days is the ability to automatically align quotation marks, uppercase “T” characters, etc. slightly past the box margin so they appear more visually balanced.

body {
  text-align: optical left;
}Code language: CSS (css)
Two examples of the same text passage, the right version showcasing optical margin alignment

Update: Amelia Bellamy-Royds helpfully pointed out that this may be partially addressed by the hanging-punctuation property. It’s only supported in Safari as of this writing, but it looks like a promising step!

Gradients can look pretty gnarly in browsers without some easing applied! Crossing my fingers that this eventually makes it into the CSS spec.

.example {
  background-image: linear-gradient(to bottom, cubic-bezier(0.455, 0.03, 0.515, 0.955), #456BD9, #F14CA3);
}Code language: CSS (css)
A gradient (from pink to blue) without easing on the left, and with easing on the right
Illustration by Arianna Chau

Comments

Tommy Carlier said:

Pseudo-elements between items can currently be created as follows:

.breadcrumbs > *:not(:first-child)::before { ... }
Code language: CSS (css)

Replies to Tommy Carlier

Tyler Sticka (Article Author ) replied:

Thanks, Tommy! I have a slight preference for this selector (less specificity):

.breadcrumbs > * + *::before { }
Code language: CSS (css)

I don’t see either technique used in the wild as often as I’d like, which is why I thought a simplified selector might help.

Tommy Hodgins replied:

Nice! It would be simple to preprocess CSS containing a custom pseudo-element selector like *::--between to become * ~ *::before in the output, but if you wanted to work with something like that client-side browsers would toss out any custom pseudo-element selectors like that it found…but browsers will keep around any pseudo-element selector that begins with ::-webkit-, so it is very easy to support something like ::-webkit-between even in the browser with a very small amount of JS: https://codepen.io/tomhodgins/pen/qBEGJLO

Illjah replied:

We recently made a class .comma, for comma-separated content, and we had to deal with ::empty elements if there were some. Decause if something went wrong, we had something like this: apple, orange, , banana. It would be great for CSS to handle it automatically

Kingbasa said:

i am just thinking
line-height only when multilined
or
line: top bottom
or
line-height: 1 21px
when multilined then 2qpx otherwise just 1

i had this issue so many times to get icons and texts and height issues set when

icon + text

just exists

Felix Gaebler said:

What about a opposite selector for “+” like “-” to select the previous element.
There are many uses for it.. one is a ‘glow’ of one list item, when you set the primary color on the hovered element and a slightly lighter color on the next and previous element.

Marc said:

I’d love to see something like:

white-space: nowidows

to avoid widowed words on the last line of a paragraph.

Kerry Johnson said:

I agree with everything you’ve said.

It would be nice to expose some basic scroll states to CSS. A use case would be to apply an overlay/arrow at the container edge to clue users in that something is scrollable.

.container::scrollable-x-start {
  ... Apply styles at start of scroll ...
}
.container::scrollable-x-end {
  ... Apply styles at end of scroll ...
}
.container:not(::scrollable-x-start):not(::scrollable-x-end) {
  ... Apply styles in between ...
}
Code language: CSS (css)

Maybe a hex shorthand like #fa to represent #fafafa would be neat.

Also, we have relative height height: 100% that requires all parent elements to have it set as well. We have a viewport height height: 100vh. I think you know where I’m leading you since we’ve all ran into the issue of backgrounds abruptly stopping when scrolling. So why not a document height that is the entire length of the document, scrollbar and all with height: 100dh? I guess it’s easier said than done for them not to implement this annoyance by now.

Kris Dages said:

I’d love to see a a value for display like contents but that would be truly transparent to css so that sibling and descendant selectors would apply to the effective visual tree.