Tag: Through

Weaving a Line Through Text in CSS

Earlier this year, I came across this demo by Florin Pop, which makes a line go either over or under the letters of a single line heading. I thought this was a cool idea, but there were a few little things about the implementation I felt I could simplify and improve at the same time.

First off, the original demo duplicates the headline text, which I knew could be easily avoided. Then there’s the fact that the length of the line going through the text is a magic number, which is not a very flexible approach. And finally, can’t we get rid of the JavaScript?

So let’s take a look into where I ended up taking this.

HTML structure

Florin puts the text into a heading element and then duplicates this heading, using Splitting.js to replace the text content of the duplicated heading with spans, each containing one letter of the original text.

Already having decided to do this without text duplication, using a library to split the text into characters and then put each into a span feels a bit like overkill, so we’re doing it all with an HTML preprocessor.

- let text = 'We Love to Play'; - let arr = text.split('');  h1(role='image' aria-label=text)   - arr.forEach(letter => {     span.letter #{letter}   - });

Since splitting text into multiple elements may not work nicely with screen readers, we’ve given the whole thing a role of image and an aria-label.

This generates the following HTML:

<h1 role="image" aria-label="We Love to Play">   <span class="letter">W</span>   <span class="letter">e</span>   <span class="letter"> </span>   <span class="letter">L</span>   <span class="letter">o</span>   <span class="letter">v</span>   <span class="letter">e</span>   <span class="letter"> </span>   <span class="letter">t</span>   <span class="letter">o</span>   <span class="letter"> </span>   <span class="letter">P</span>   <span class="letter">l</span>   <span class="letter">a</span>   <span class="letter">y</span> </h1>

Basic styles

We place the heading in the middle of its parent (the body in this case) by using a grid layout:

body {   display: grid;   place-content: center; }
Screenshot of grid layout lines around the centrally placed heading when inspecting it with Firefox DevTools.
The heading doesn’t stretch across its parent to cover its entire width, but is instead placed in the middle.

We may also add some prettifying touches, like a nice font or a background on the container.

Next, we create the line with an absolutely positioned ::after pseudo-element of thickness (height) $ h:

$ h: .125em; $ r: .5*$ h;  h1 {   position: relative;      &::after {     position: absolute;     top: calc(50% - #{$ r}); right: 0;     height: $ h;     border-radius: 0 $ r $ r 0;     background: crimson;   } }

The above code takes care of the positioning and height of the pseudo-element, but what about the width? How do we make it stretch from the left edge of the viewport to the right edge of the heading text?

Line length

Well, since we have a grid layout where the heading is middle-aligned horizontally, this means that the vertical midline of the viewport coincides with that of the heading, splitting both into two equal-width halves:

SVG illustration. Shows how the vertical midline of the viewport coincides with that of the heading and splits both into equal width halves.
The middle-aligned heading.

Consequently, the distance between the left edge of the viewport and the right edge of the heading is half the viewport width (50vw) plus half the heading width, which can be expressed as a % value when used in the computation of its pseudo-element’s width.

So the width of our ::after pseudo-element is:

width: calc(50vw + 50%);

Making the line go over and under

So far, the result is just a crimson line crossing some black text:

What we want is for some of the letters to show up on top of the line. In order to get this effect, we give them (or we don’t give them) a class of .over at random. This means slightly altering the Pug code:

- let text = 'We Love to Play'; - let arr = text.split('');  h1(role='image' aria-label=text)   - arr.forEach(letter => {     span.letter(class=Math.random() > .5 ? 'over' : null) #{letter}   - });

We then relatively position the letters with a class of .over and give them a positive z-index.

.over {   position: relative;   z-index: 1; }

My initial idea involved using translatez(1px) instead of z-index: 1, but then it hit me that using z-index has both better browser support and involves less effort.

The line passes over some letters, but underneath others:

Animate it!

Now that we got over the tricky part, we can also add in an animation to make the line enter in. This means having the crimson line shift to the left (in the negative direction of the x-axis, so the sign will be minus) by its full width (100%) at the beginning, only to then allow it to go back to its normal position.

@keyframes slide { 0% { transform: translate(-100%); } }

I opted to have a bit of time to breathe before the start of the animation. This meant adding in the 1s delay which, in turn, meant adding the backwards keyword for the animation-fill-mode, so that the line would stay in the state specified by the 0% keyframe before the start of the animation:

animation: slide 2s ease-out 1s backwards;

A 3D touch

Doing this gave me another idea, which was to make the line go through every single letter, that is, start above the letter, go through it and finish underneath (or the other way around).

This requires real 3D and a few small tweaks.

First off, we set transform-style to preserve-3d on the heading since we want all its children (and pseudo-elements) to a be part of the same 3D assembly, which will make them be ordered and intersect according to how they’re positioned in 3D.

Next, we want to rotate each letter around its y-axis, with the direction of rotation depending on the presence of the randomly assigned class (whose name we change to .rev from “reverse” as “over” isn’t really suggestive of what we’re doing here anymore).

However, before we do this, we need to remember our span elements are still inline ones at this point and setting a transform on an inline element has absolutely no effect.

To get around this issue, we set display: flex on the heading. However, this creates a new issue and that’s the fact that span elements that contain only a space (" ") get squished to zero width.

Screenshot showing how the span containing only a space gets squished to zero width when setting `display: flex` on its parent.
Inspecting a space only <span> in Firefox DevTools.

A simple fix for this is to set white-space: pre on our .letter spans.

Once we’ve done this, we can rotate our spans by an angle $ a… in one direction or the other!

$ a: 2deg;  .letter {   white-space: pre;   transform: rotatey($ a); }  .rev { transform: rotatey(-$ a); }

Since rotation around the y-axis squishes our letters horizontally, we can scale them along the x-axis by a factor ($ f) that’s the inverse of the cosine of $ a.

$ a: 2deg; $ f: 1/cos($ a)  .letter {   white-space: pre;   transform: rotatey($ a) scalex($ f) }  .rev { transform: rotatey(-$ a) scalex($ f) }

If you wish to understand the why behind using this particular scaling factor, you can check out this older article where I explain it all in detail.

And that’s it! We now have the 3D result we’ve been after! Do note however that the font used here was chosen so that our result looks good and another font may not work as well.

The post Weaving a Line Through Text in CSS appeared first on CSS-Tricks.


, , ,

Thinking Through Styling Options for Web Components

Where do you put styles in web components?

I’m assuming that we’re using the Shadow DOM here as, to me, that’s one of the big draws of a web component: a platform thing that is a uniquely powerful thing the platform can do. So this is about defining styles for a web component in a don’t-leak-out way, and less so a way to get global styles to leak in (although that’s very interesting as well, which can be done via custom properties which we’ll look at later in the article).

If you’re building the template inside the JavaScript — which is nice because of template literals and how we can sprinkle our data into the template nicely — you need access to those styles in JavaScript.

const template = `   <style>$  {styles}</style>   <div class="$  {class}">     <h2>$  Thinking Through Styling Options for Web Components</h2>     $  {content}   </div> `;

Where does that style variable come from? Maybe also a template literal?

const style = `   :host {     background: white;   }   h2 {     font: 900 1.5rem/1.1 -system-ui, sans-serif;   } `;

I guess that’s fine, but it makes for a big messy block of code just dunked somewhere in the class where you’re trying to build this web component.

Another way is to <template> the template and make a <style> block part of it.

<template id="card-template">   <style>     :host {       background: white;     }     h2 {       font: 900 1.5rem/1.1 -system-ui, sans-serif;     }   </style>    <div id="card-hook">     <h2 id="title-hook"></h2>     <p id="desc-hook"></p>   </div> </template>

I can see the appeal with this because it keeps HTML in HTML. What I don’t love about it is that you have to do a bunch of manual shadowRoot.querySelector("#title-hook").innerHTML = myData.title; work in order to flesh out that template. That doesn’t feel like a convenient template. I also don’t love that you need to just chuck this template somewhere in your HTML. Where? I dunno. Just chuck it in there. Chuck it.

The CSS is moved out of the JavaScript too, but it just moved from one awkward location to another.

If we wanted to keep the CSS in a CSS file, we can sorta do that like this:

<template id="card-template">   <style>     @import "/css/components/card.css";   </style>    <div id="card-hook">     <h2 id="title-hook"></h2>     <p id="desc-hook"></p>   </div> </template>

(The use of <link rel="import" type="css" href=""> is deprecated, apparently.)

Now we have @import which is an extra HTTP Request, and notorious for being a performance hit. An article by Steven Lambert says it clocked in at half a second slower. Not ideal. I don’t suppose it would be much better to do this instead:

class MyComponent extends HTMLElement {        constructor() {     super();     this.attachShadow({ mode: "open" });      fetch('/css/components/card.css')       .then(response => response.text())       .then(data => {         let node = document.createElement('style');         node.innerHTML = data;         document.body.appendChild(node);       });   }    // ... }

Seems like that would potentially be a Flash-of-Unstyled-Web-Component? I guess I should get off my butt and test it.

Now that I’m digging into this again, it seems like ::part has gotten some steam (explainer). So I can do…

const template = `   <div part="card">     <h2>$  Thinking Through Styling Options for Web Components</h2>     $  {content}   </div> `;

…then write styles in a global stylesheet that only apply inside that Shadow DOM, like:

my-card::part(card) {   background: black;   color: white; }

…which has a smidge of browser support, but maybe not enough?

These “part” selectors can only touch the exact element it’s connected to. You’d have to do all your styling by applying a part name to every single DOM node and then styling each entirely on its own. That’s no fun, particularly because the appeal of the Shadow DOM is this isolated styling environment in which we’re supposed to be able to write looser CSS selectors and not be worried our h2 { } style is going to leak all over the place.

Looks like if native CSS modules becomes a thing, that will be the most helpful thing that could happen.

import styles from './styles.css';  class MyElement extends HTMLElement {   constructor() {     this.attachShadow({mode: open});     this.shadowRoot.adoptedStyleSheets = [styles];   } }

I’m not sure, however, if this is any sort of performance boost. Seems like it would be a wash between this and @import. I have to say I prefer the clarity and syntax with native CSS modules. It’s nice to be writing JavaScript when working with JavaScript.

Constructable Stylesheets also look helpful for sharing a stylesheet across multiple components. But the CSS modules approach looks like it could also do that since the stylesheet has already become a variable at that point.

The post Thinking Through Styling Options for Web Components appeared first on CSS-Tricks.


, , , ,

“All these things are quite easy to do, they just need somebody to sit down and just go through the website”

I saw a video posted on Twitter from Channel 5 News in the UK (I have no idea what the credibility of them is, it’s an ocean away from me) with anchor Claudia Liza asking Glen Turner and Kristina Barrick questions about website accessibility.

Apparently, they often post videos with captions, but this particular video doesn’t (ironically). So, I’ve transcribed it here as I found them pretty well-spoken.

[Claudia Liza]: … you do have a visual impairment. How does that make it difficult for you to shop online?

[Glen Turner]: Well, I use various special features on my devices to shop online to make it easier. So, I enlarge the text, I’ll invert the colors to make the background dark so that I don’t have glare. I will zoom in on pictures, I will use speech to read things to me because it’s too difficult sometimes. But sometimes websites and apps aren’t designed in a way that is compatible with that. So sometimes the text will be poorly contrasted so you’ll have things like brown on black, or red on black, or yellow on white, something like that. Or the menu system won’t be very easy to navigate, or images won’t have descriptions for the visually impaired because images can have descriptions embedded that a speech reader will read back to them. So all these various factors make it difficult or impossible to shop on certain websites.

[Claudia Liza]: What do you need retailers to do? How do they need to change their technology on their websites and apps to make it easier?

It’s quite easy to do a lot of these things, really. Check the colors on your website. Make sure you’ve got light against dark and there is a very clear distinctive contrast. Make sure there are descriptions for the visually impaired. Make sure there are captions on videos for the hearing impaired. Make sure your menus are easy to navigate and make it easy to get around. All these things are quite easy to do, they just need somebody to sit down and just go through the website and check that it’s all right and consult disabled people as well. Ideally, you’ve got disabled people in your organization you employ, but consult the wider disabled community as well. There is loads of us online there is loads of us spread all over the country. There is 14 million of us you can talk to, so come and talk to us and say, “You know, is our website accessible for you? What can we do to improve it?” Then act on it when we give you our advice.

[Claudia Liza]: It makes sense doesn’t it, Glen? It sounds so simple. But Christina, it is a bit tricky for retailers. Why is that? What do other people with disabilities tell you?

So, we hear about content on websites being confusing in the way it’s written. There’s lots of information online about how to make an accessible website. There’s a global minimum legal standard called WCAG and there’s lot of resources online. Scope has their own which has loads of information on how to make your website accessible.

I think the problem really is generally lack of awareness. It doesn’t get spoken about a lot. I think that disabled consumers – there’s not a lot of places to complain. Sometimes they’ll go on a website and there isn’t even a way to contact that business to tell them that their website isn’t accessible. So what Scope is trying to do is raise the voices of disabled people. We have crowdsourced a lot of people’s feedback on where they experience inaccessible websites. We’re raising that profile and trying to get businesses to change.

[Claudia Liza]: So is it legal when retails aren’t making their websites accessible?

Yeah, so, under the Equality Act 2010, it’s not legal to create an inaccessible website, but what we’ve found is that government isn’t generally enforcing that as a law.

[Claudia Liza]: Glenn, do you feel confident that one day you’ll be able to buy whatever you want online?

I would certainly like to think that would be the case. As I say, you raise enough awareness and get the message out there and alert business to the fact that there is a huge consumer market among the disabled community, and we’ve got a 274 billion pound expenditure a year that we can give to them. Then if they are aware of that, then yeah, hopefully they will open their doors to us and let us spend our money with them.

The post “All these things are quite easy to do, they just need somebody to sit down and just go through the website” appeared first on CSS-Tricks.


, , , , , , , , , , ,

Perceived Velocity through Version Numbers

HTML5 and CSS3 were big. So big that they were buzzwords that actually meant something and were a massive success story in pushing web technology forward. JavaScript names their big releases now too: ES6, ES7, ES8… and it seems like it will keep going that way.

But HTML and CSS are done with that game. Shortly after the whole HTML5/CSS3 thing, the message was that there will be no HTML6/CSS4. There are reasons for that, like perhaps it’s healthier for CSS modules to evolve independently of some global versioning number.

That said… as Dave says:

… the lull in excitement since those days is palpable….

People aren’t equally excited about the big three languages of the web.

I’m on a bit of a quest to understand why these three technologies built to work together are so unequally yoked in popularity and their communities polarized from one another. One end of the spectrum experiences a boom while the other experiences a bust. The rising tide does not lift all boats.

Surely a major version number release for HTML and CSS could spark a ton of fresh enthusiasm.

I’ll help. HTML6 could have HTML imports for web components, <include>, and a multi-select. CSS4 gets container queries, subgrid, standardized form control styling, and transitions to auto dimensions.

Direct Link to ArticlePermalink

The post Perceived Velocity through Version Numbers appeared first on CSS-Tricks.


, , , ,

Would You Watch a Documentary Walking Through Codebases?

This resonated pretty strongly with people:

I think I was watching some random Netflix documentary and daydreaming that the subject was actually something I was super interested in: a semi-high-quality video deep dive into different companies codebases, hearing directly from the developers that built and maintain them.

Horror stories might also be interesting. Particularly if they involve perfect storm scenarios that naturally take us on a tour of the codebase along the way, so we can see how the system failed. We get little glimpses of this sometimes.

Probably more interesting is a tour of codebases when everything is humming along as planned. I wanna see the bottling factory when it’s working efficiently so I can see the symphony of it more than I wanna see a heaping pile of broken glass on the floor.

Or! Maybe the filmmaker will get lucky and there will be some major problem with the site as they’re filming, and they can capture the detection, reaction, and fixing of the problem and everything that entails. And sure, this isn’t wildlife rescue; sometimes the process for fixing even the worst of fires is to stare at your screen and type in silence like you always do. But I’m sure there is some way to effectively show the drama of it.

I’m not sure anything like this exists yet, but I’d definitely watch it. Here’s a bunch of stuff that isn’t a million miles away from the general idea:

  • This Developer’s Life was damn well done and ran mostly from 2010-2012, but with an episode as recent as 2015.
  • The History of the Web is a blog/newsletter about… that.
  • There is a subreddit for /r/WatchPeopleCode. But there is a crapload of coding videos on YouTube and Twitch and all over that are equally sufficient.
  • It’s been a few years since a new episode has been released, but readthesource shows developers going through the source code of big projects they’re working on.

Design is lucky, they’ve got a bunch of great high-budget documentaries like Objectified, Helvetica, Design & Thinking, Design Disruptors, Design is Future, and Abstract.

  • Web design has What Comes Next is the Future.
  • The post Would You Watch a Documentary Walking Through Codebases? appeared first on CSS-Tricks.


    , , , , ,