Tag: Some

Some React Blog Posts I’ve Bookmarked and Read Lately

  • The React Hooks Announcement In Retrospect: 2 Years Later — Ryan Carniato considers hooks to be the most significant turning point in front end in the past five years, but he also says hooks have muddied the waters as well.
  • Mediator Component in React — Robin Wieruch’s article made me think just how un-opinionated React is and how architecturally on-your-own you are. It’s tough to find the right abstractions.
  • No One Ever Got Fired for Choosing React — Jake Lazaroff’s article is a good balance to the above. Sometimes you pick a library like React because it solves problems you’re likely to run into and lets you get to work.
  • A React “if component — I kinda like how JSX does conditional rendering, but hey, a lightweight abstraction like this might just float your boat.
  • State of the React Ecosystem in 2021 — Hooks are big. State management is all over the place, and state machines are growing in popularity. webpack is still the main bundler. Everyone is holding their breath about Suspense… so suspenseful.
  • Blitz.js — “The Fullstack React Framework” — interesting to see a framework built on top of another framework (Next.js).
  • Introducing Zero-Bundle-Size React Server Components — Feels like it will be a big deal, but will shine brightest when frameworks and hosts zero-in on offerings around it. I’m sure Vercel and Netlify are all  👀.

The post Some React Blog Posts I’ve Bookmarked and Read Lately appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , , ,

Some Typography Blog Posts I’ve Bookmarked and Read Lately

  • Font-size: An Unexpectedly Complex CSS Property — From Manish Goregaokar in 2017. Of many oddities, I found the one where font: medium monospace renders at 13px where font: medium sans-serif renders at 16px particularly weird.
  • The good line-height — Since CSS supports unitless line-height, you probably shouldn’t be setting a hard number anyway.
  • Time to Say Goodbye to Google Fonts — Simon Wicki doesn’t mean don’t use them, they mean self-host them. Browsers are starting to isolate cache on a per-domain basis so that old argument that you buy speed because “users probably already have it cached” doesn’t hold up. I expected to hear about stuff like having more control over font loading, but this is just about the cache.
  • My Favorite Typefaces of 2020 — John Boardley’s picks for the past year. Have you seen these “color fonts”? They are so cool. Check out LiebeHeide, it looks like real pen-on-paper.
  • How to avoid layout shifts caused by web fonts — We’ve got CLS (Cumulative Layout Shift) now and it’s such an important performance metric that will soon start affecting SEO. And because we have CSS control over font loading via font-display, that means if we set things up such that font loading shifts the page, that’s bad. I like Simon Hearne’s suggestion that we tweak both our custom font and fallback font to match perfectly. I think perfect fallback fonts are one of the best CSS tricks.
  • How to pick a Typeface for User Interface and App Design? — Oliver Schöndorfer makes the case for “functional text” which is everything that isn’t body text (e.g. paragraphs of text) or display text (e.g. headers). “Clarity is key.”

The post Some Typography Blog Posts I’ve Bookmarked and Read Lately appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , , ,
[Top]

Some Performance Blog Posts I’ve Bookmarked and Read Lately

  • Back/forward cache — I always assumed browsers just do fancy stuff with the back/forward buttons and us developers had very little control. Philip Walton tells us it’s critical that we understand “what makes pages eligible (and ineligible) for bfcache to maximize their cache-hit rates.” For example, if you use the unload event, the page is instantly disqualified from the cache.
  • Big picture performance analysis using Lighthouse Parade — Lighthouse only tests one page of your site. Lighthouse Parade tests all the URLs of a site, and aggregates the results.
  • Beyond fast with new performance features — Jake Archibald gets into the CSS content-visibility property (and a few other things) and how it can lead to incredible performance boosts (you use it to tell the browser that it’s straight-up OK not to render things). Right this minute, content-visiblity makes me nervous as it has issues with scrollbar jankiness and accessiblity problems. I found it a smidge confusing at first glance, and Tim Kadlec has reservations.
  • Image Decode & Visual Timings — Image performance isn’t only about the size of the image. Different formats take different amounts of time to decode and render. GIF never wins.
  • How to increase CSS-in-JS performance by 175x — The trick, readers, is shipping CSS. You can still use CSS-in-JS as you author, and have the build process create the CSS. They call that “Zero-Runtime” like Linaria.
  • Testing Performance — Kelly Sutton: “The best approach that I have found to preventing performance regressions is to employ qualitative assessments of the code.” Performance is such an unwieldy beast, that only in production will you truly know what happens.
  • Front-End Performance Checklist 2021 — If you’re going to get serious about performance this year, you’d do well to dig into Vitaly’s guide.
  • We rendered a million web pages to find out what makes the web slow — HTTP/2 is a huge indicator of good performance.

The post Some Performance Blog Posts I’ve Bookmarked and Read Lately appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , , ,
[Top]

Some Recent Videos About Websites That Are Pretty Good

Here’s a little hodgepodge of videos I’ve recently bookmarked (and watched). I couldn’t decide if each one of them should be a separate blog post or if I should do this combined list post thing. If I had a lot more to say about each video I would have split them off, but I went with the combined post and fewer words here. Let me know in the comments if you have a preference on that kind of thing.

Here’s Tom Scott explaining why the web is such a mess

Cookies. It all cookies fault. Kinda. Also humans.

This is the same Tom that did that super neat video that updated it’s own title with the view count.

I don’t know this person’s name but I appreciated how it gets the details right in this recreation of the Discord sidebar

Except the fact that the :hover was on the <li> itself rather than a link that went somewhere sensible, but hey, I guess it’s slightly better than the actual Discord markup where it’s <div class="listItem_">.

Heydon gets all weird about progressive enhancment

I can’t embed it here because, even though it looks like Heydon switched over to Vimeo rather than just straight up <video> tags, the privacy settings have it locked to briefs.video only.

I liked the point about “the basic layout is not a broken layout,” except, doesn’t it seem like in that exact case it wouldn’t matter if you wrapped the grid-template-rows in a @supports or not? I love that @supports is a thing, and even more so now that we’ve passed the awkward years where @supports itself didn’t have full browser support, but I don’t find myself reaching for it that much, as it’s only really useful if you need to do something different than “just let it not work,” which I don’t find terribly common.

Houssein Djirdeh and Jason Miller get into “modern JavaScript”

We’ve gotta be so careful about compiled code. There is an example where one line of JavaScript gets compiled into 7000 bytes, which is bigger and far slower than intended. Taking care of older browsers when you have a significant number of users using that old browser is a really great thing, but you might be surprised at the browser support of “modern JavaScript” and find you are compiling more than you need to.

The kicker is that you only really control what you write, but probably most of what you ship is third-party. That means npm, which is absolutely loaded with very non-modern JavaScript. The sweet spot, they say, is calling ES 2017 the compile target in general. If you need even older support, use the ol’ differential serving trick.

There’s a blog version of this video, too.

Jessica Chan challenges William Candillon to a CSSBattle

Like literally CSSBattle, the website.

They go back and forth trying to figure out how to make this little spiky virus-looking thing. I totally relate to their approaches! Neither of them are like amazingly clever with either the HTML or CSS — they just try to get it done. That’s why I could never get into CSSBattle myself. I appreciate people’s trickery (duh), but my actual CSS writing style is almost like verbose-on-purpose.


The post Some Recent Videos About Websites That Are Pretty Good appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , ,
[Top]

Create a Tag Cloud with some Simple CSS and even Simpler JavaScript

I’ve always liked tag clouds. I like the UX of seeing what tags are most popular on a website by seeing the relative font size of the tags, popular tags being bigger. They seem to have fallen out of fashion, though you do often see versions of them used in illustrations in tools like Wordle.

How difficult is it to make a tag cloud? Not very difficult at all. Let’s see!

Let’s start with the markup

For our HTML, we’re going to put each of our tags into a list, <ul class="tags"><ul>. We’ll be injecting into that with JavaScript.

If your tag cloud is already in HTML, and you are just looking to do the relative font-size thing, that’s good! Progressive enhancement! You should be able to adapt the JavaScript later on so it does just that part, but not necessarily building and injecting the tags themselves.

I have mocked out some JSON with a certain amount of articles tagged with each property. Let’s write some JavaScript to go grab that JSON feed and do three things.

First, it we’ll create an <li> from each entry for our list. Imagine the HTML, so far, is like this:

<ul class="tags">   <li>align-content</li>   <li>align-items</li>   <li>align-self</li>   <li>animation</li>   <li>...</li>   <li>z-index</li> </ul>

Second, we’ll put the number of articles each property has in parentheses beside inside each list item. So now, the markup is like this:

<ul class="tags">   <li>align-content (2)</li>   <li>align-items (2)</li>   <li>align-self (2)</li>   <li>animation (9)</li>   <li>...</li>   <li>z-index (4)</li> </ul>

Third, and last, we’ll create a link around each tag that goes to the correct place. This is where we can set the font-size property for each item depending on how many articles that property is tagged with, so animation that has 13 articles will be much bigger than background-color which only has one article.

<li class="tag">   <a     class="tag__link"     href="https://example.com/tags/animation"     style="font-size: 5em">     animation (9)   </a> </li>

The JavasScript part

Let’s have a look at the JavaScript to do this.

const dataURL =   "https://gist.githubusercontent.com/markconroy/536228ed416a551de8852b74615e55dd/raw/9b96c9049b10e7e18ee922b4caf9167acb4efdd6/tags.json"; const tags = document.querySelector(".tags"); const fragment = document.createDocumentFragment(); const maxFontSizeForTag = 6;  fetch(dataURL)   .then(function (res) {     return res.json();   })   .then(function (data) {     // 1. Create a new array from data     let orderedData = data.map((x) => x);     // 2. Order it by number of articles each tag has     orderedData.sort(function(a, b) {       return a.tagged_articles.length - b.tagged_articles.length;     });     orderedData = orderedData.reverse();     // 3. Get a value for the tag with the most articles     const highestValue = orderedData[0].tagged_articles.length;     // 4. Create a list item for each result from data.     data.forEach((result) => handleResult(result, highestValue));     // 5. Append the full list of tags to the tags element     tags.appendChild(tag);   });

The JavaScript above uses the Fetch API to fetch the URL where tags.json is hosted. Once it gets this data, it returns it as JSON. Here we seque into a new array called orderedData (so we don’t mutate the original array), find the tag with the most articles. We’ll use this value later on in a font-scale so all other tags will have a font-size relative to it. Then, forEach result in the response, we call a function I have named handleResult() and pass the result and the highestValue to this function as a parameter. It also creates:

  • a variable called tags which is what we will use to inject each list item that we create from the results,
  • a variable for a fragment to hold the result of each iteration of the loop, which we will later append to the tags, and
  • a variable for the max font size, which we’ll use in our font scale later.

Next up, the handleResult(result) function:

function handleResult(result, highestValue) {   const tag = document.createElement("li");   tag.classList.add("tag");   tag.innerHTML = `<a class="tag__link" href="$ {result.href}" style="font-size: $ {result.tagged_articles.length * 1.25}em">$ {result.title} ($ {result.tagged_articles.length})</a>`;    // Append each tag to the fragment   fragment.appendChild(tag); }

This is pretty simple function that creates a list element set to the variable named tag and then adds a .tag class to this list element. Once that’s created, it sets the innerHTML of the list item to be a link and populates the values of that link with values from the JSON feed, such as a result.href for the link to the tag. When each li is created, it’s then added as a string to the fragment, which we will later then append to the tags variable. The most important item here is the inline style tag that uses the number of articles—result.tagged_articles.length—to set a relative font size using em units for this list item. Later, we’ll change that value to a formula to use a basic font scale.

I find this JavaScript just a little bit ugly and hard on the eyes, so let’s create some variables and a simple font scale formula for each of our properties to tidy it up and make it easier to read.

function handleResult(result, highestValue) {   // Set our variables   const name = result.title;   const link = result.href;   const numberOfArticles = result.tagged_articles.length;   let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;   fontSize = +fontSize.toFixed(2);   const fontSizeProperty = `$ {fontSize}em`;    // Create a list element for each tag and inline the font size   const tag = document.createElement("li");   tag.classList.add("tag");   tag.innerHTML = `<a class="tag__link" href="$ {link}" style="font-size: $ {fontSizeProperty}">$ {name} ($ {numberOfArticles})</a>`;      // Append each tag to the fragment   fragment.appendChild(tag); }

By setting some variables before we get into creating our HTML, the code is a lot easier to read. And it also makes our code a little bit more DRY, as we can use the numberOfArticles variable in more than one place.

Once each of the tags has been returned in this .forEach loop, they are collected together in the fragment. After that, we use appendChild() to add them to the tags element. This means the DOM is manipulated only once, instead of being manipulated each time the loop runs, which is a nice performance boost if we happen to have a large number of tags.

Font scaling

What we have now will work fine for us, and we could start writing our CSS. However, our formula for the fontSize variable means that the tag with the most articles (which is “flex” with 25) will be 6em (25 / 25 * 6 = 6), but the tags with only one article are going to be 1/25th the size of that (1 / 25 * 6 = 0.24), making the content unreadable. If we had a tag with 100 articles, the smaller tags would fare even worse (1 / 100 * 6 = 0.06).

To get around this, I have added a simple if statement that if the fontSize that is returned is less than 1, set the fontSize to 1. If not, keep it at its current size. Now, all the tags will be within a font scale of 1em to 6em, rounded off to two decimal places. To increase the size of the largest tag, just change the value of maxFontSizeForTag. You can decide what works best for you based on the amount of content you are dealing with.

function handleResult(result, highestValue) {   // Set our variables   const numberOfArticles = result.tagged_articles.length;   const name = result.title;   const link = result.href;   let fontSize = numberOfArticles / highestValue * maxFontSizeForTag;   fontSize = +fontSize.toFixed(2);      // Make sure our font size will be at least 1em   if (fontSize <= 1) {     fontSize = 1;   } else {     fontSize = fontSize;   }   const fontSizeProperty = `$ {fontSize}em`;      // Then, create a list element for each tag and inline the font size.   tag = document.createElement("li");   tag.classList.add("tag");   tag.innerHTML = `<a class="tag__link" href="$ {link}" style="font-size: $ {fontSizeProperty}">$ {name} ($ {numberOfArticles})</a>`;    // Append each tag to the fragment   fragment.appendChild(tag); }

Now the CSS!

We’re using flexbox for our layout since each of the tags can be of varying width. We then center-align them with justify-content: center, and remove the list bullets.

.tags {   display: flex;   flex-wrap: wrap;   justify-content: center;   max-width: 960px;   margin: auto;   padding: 2rem 0 1rem;   list-style: none;   border: 2px solid white;   border-radius: 5px; }

We’ll also use flexbox for the individual tags. This allows us to vertically align them with align-items: center since they will have varying heights based on their font sizes.

.tag {   display: flex;   align-items: center;   margin: 0.25rem 1rem; }

Each link in the tag cloud has a small bit of padding, just to allow it to be clickable slightly outside of its strict dimensions.

.tag__link {   padding: 5px 5px 0;   transition: 0.3s;   text-decoration: none; }

I find this is handy on small screens especially for people who might find it harder to tap on links. The initial text-decoration is removed as I think we can assume each item of text in the tag cloud is a link and so a special decoration is not needed for them.

I’ll just drop in some colors to style things up a bit more:

.tag:nth-of-type(4n+1) .tag__link {   color: #ffd560; } .tag:nth-of-type(4n+2) .tag__link {   color: #ee4266; } .tag:nth-of-type(4n+3) .tag__link {   color: #9e88f7; } .tag:nth-of-type(4n+4) .tag__link {   color: #54d0ff; }

The color scheme for this was stolen directly from Chris’ blogroll, where every fourth tag starting at tag one is yellow, every fourth tag starting at tag two is red, every fourth tag starting at tag three is purple. and every fourth tag starting at tag four is blue.

Screenshot of the blogroll on Chris Coyier's personal website, showing lots of brightly colored links with the names of blogs included in the blogroll.

We then set the focus and hover states for each link:

.tag:nth-of-type(4n+1) .tag__link:focus, .tag:nth-of-type(4n+1) .tag__link:hover {   box-shadow: inset 0 -1.3em 0 0 #ffd560; } .tag:nth-of-type(4n+2) .tag__link:focus, .tag:nth-of-type(4n+2) .tag__link:hover {   box-shadow: inset 0 -1.3em 0 0 #ee4266; } .tag:nth-of-type(4n+3) .tag__link:focus, .tag:nth-of-type(4n+3) .tag__link:hover {   box-shadow: inset 0 -1.3em 0 0 #9e88f7; } .tag:nth-of-type(4n+4) .tag__link:focus, .tag:nth-of-type(4n+4) .tag__link:hover {   box-shadow: inset 0 -1.3em 0 0 #54d0ff; }

I could probably have created a custom variable for the colors at this stage—like --yellow: #ffd560, etc.—but decided to go with the longhand approach for IE 11 support. I love the box-shadow hover effect. It’s a very small amount of code to achieve something much more visually-appealing than a standard underline or bottom-border. Using em units here means we have decent control over how large the shadow would be in relation to the text it needed to cover.

OK, let’s top this off by setting every tag link to be black on hover:

.tag:nth-of-type(4n+1) .tag__link:focus, .tag:nth-of-type(4n+1) .tag__link:hover, .tag:nth-of-type(4n+2) .tag__link:focus, .tag:nth-of-type(4n+2) .tag__link:hover, .tag:nth-of-type(4n+3) .tag__link:focus, .tag:nth-of-type(4n+3) .tag__link:hover, .tag:nth-of-type(4n+4) .tag__link:focus, .tag:nth-of-type(4n+4) .tag__link:hover {   color: black; }

And we’re done! Here’s the final result:


The post Create a Tag Cloud with some Simple CSS and even Simpler JavaScript appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , , , ,
[Top]

Some Industry Podcasts

Clearleft made a 6-episode Season One

It’s called The Clearleft Podcast if you can believe that. It gets into new (at least to me) concepts like Design Ops and Design Sprints, which are loaded terms and need nuanced discussion. It’s really well-edited, pulling in clips from relevant talks and such. A cut above the hit-record-hit-stop ‘n’ polish podcasts that I typically do.

If you like Jeremy’s soothing radio voice, he also narrated our Web History series.

Syntax on CSS

The fellas (Wes and Scott) do a good job of covering the landscape of CSS in 2020. I particularly like the pragmatism here, as they poo-poo on nothing, but rather attempt to pair many of the approaches the discuss to particular development situations.

They also had Adam Argyle on the show to talk about how things end up in CSS.

Netlify has a podcast now

It’s called Remotely Interesting. You’d think it would be the all-Jamstack-all-the-time show (which I’d totally listen to) but the gang over there tackles broad topics, talking about stuff like blogging, passion, and communication (in addition to Jamstack-y stuff, of course).

Igalia Chats: Web Ecosystem Health

An episode with a very tough discussion about what is good for the web and what isn’t.

Igalia’s Brian Kardell sits down with Jeremy Keith and Stuart Langridge to chat about rendering engine diversity, history and the health of the web browser ecosystem.

Solving Solved Problems

That’s the name of a blog post by Ahmad Nassri that was discussed in an episode of JS Party. It was sweet to hear the backstory of Amal and Ahmad and all the mutual respect there. It’s also valuable to bask in the classic build vs. buy conversations that all software companies need to take seriously.

Mine

Dave and I have been extremely consistent, publishing new episodes of ShopTalk Show every Monday. And Marie publishes new CodePen Radio episodes every week as well.


The post Some Industry Podcasts appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

Some New Icon Sets

I’ve bookmarked some icon sets lately, partly because I can never find a nice set when I need to. I figured I’d even go the extra mile here and blog them so I can definitely find them later. Aside from being nice, cohesive, and practical sets of icons, I find it interesting that literally all of them:

  • are SVG, and thus easily resizeable
  • are built with rather efficient <path> elements
  • are stroked instead of filled (at least optionally)
  • have a click-to-copy SVG feature on their site
  • are free and open source

Good job, all! Seems like people are coming around to the idea of an SVG icon system where you just… put the SVG in the HTML.

Tabler Icons

Teenyicons

Heroicons

hola svg

This one is from Mariana Beldi who recently shared how hand-drawing SVG can be so much more efficient than using an illustration tool.


The post Some New Icon Sets appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

Some Performance Links

Just had a couple of good performance links burning a hole in my pocket, so blogging them like a good little blogger.

Web Performance Recipes With Puppeteer

Puppeteer is an Node library for spinning up a copy of Chrome “headlessly” (i.e. no UI) and controlling it. People use it for stuff like taking a screenshot of a website or running integration tests. You can even run it in a Lambda.

Another use case is running synthetic (i.e. not based on real-users) performance tests, like some of these new Web Core Vitals

Addy Osmani lists out a bunch of these “recipes” for measuring certain performance things in Puppeteer. These would be super useful as part of a build process alongside other tests. Did the unit tests pass? Did the integration tests pass? Did the accessibility tests pass? Did the performance metrics tests pass?


BrowserStack SpeedLab

BrowserStack released a thing to measure your site and give you a performance score.

You get the tests back super quick which is cool. I can see how tools like this are good for starting conversations with teams about improving performance.

But… that number seems a little weird. They don’t exactly document how it’s calculated, but it seems to be based on stuff like Time to First Byte (TTFB) and the page load event, which aren’t particularly useful performance metrics.

It’s not bad that this tool exists or anything, but I don’t think it’s for practitioners doing performance work.


5 Common Mistakes Teams Make When Tracking Performance

Karolina Szczur from Calibre documents some common team struggles like, for example, having a team be able to identify real issues from variability noise.

Many people from different backgrounds can view performance dashboards. Not knowing what constitutes a meaningful change that needs investigation can result in false positives, lack of trust in monitoring and cycles spent looking for reasons for performance regressions or upgrades that aren’t there.


Are your JavaScript long tasks frustrating users?

50ms. That’s how long until any particular JavaScript task starts affecting user experience. Might as well track and (ideally) fix them.

When the browser’s main thread hits max CPU for more than 50ms, a user starts to notice that their clicks are delayed and that scrolling the page has become janky and unresponsive. Batteries drain faster. People rage click or go elsewhere.

The post Some Performance Links appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Some Typography Links

I just can’t stop opening excellent typography-related articles, which means I need to subject you to blog posts that round them up so I can clean up my open tabs.

Vistaserve is “a grass-roots web hosting initiative hailing from Thornbury, Australia. Inspired by the quirky web of the 90s, we allow users to create home pages, your own little sandbox on the World Wide Web, as it were.” Caitlin & Paul (I think the no-last-name thing is part of the aesthetic) wanted to get the fonts right, which meant removing anti-aliasing (the thing that makes fonts look good on screens!). CSS was no help. Turned out to be quite a journey involving literally rebuilding the fonts.


Thomas Bohm makes the point that the kerning around punctation may require special attention. For example, a question mark needing a little extra space or moving a superscript number away from butting against a letter.

You could do it manually with stuff like &thinsp; or &hairsp in between characters. But I’m far too lazy for that unless I’m working on a very special piece. Personally, I just cross my fingers that the font I’m using is high quality enough to have thought of and implemented this sort of attention to detail.


I’m sure we’ve all seen, “The quick brown fox jumps over the lazy dog” as a tester string for type, because it uses all the characters in the alphabet. Jonathan Hoefler created some new proofing text that is much more helpful for typographers like him.

That’s deep in the type nerd weeds there. More useful perhaps is another recent post from Jonathan on pairings. I’ve probably read dozens of posts on font pairings in my life, but this one resonates the most.

Some of the most dazzling typographic pairings — and certainly my favorites — are those that use unexpected fonts together. At left, the grey flannel suit that is Tungsten Compressed is paired with crimson silk doublet of the St. Augustin Civilité, a fiery sixteenth century typeface that demands a good foil.


If you’ve got macOS Catalina, you’ve got access to some really nice fonts you might not know about that need to be manually downloaded. Ralf Herrmann has the story on what you get:

You can download the fonts right from Font Book

I get Erik Kennedy’s Learn UI Design newsletter, and he mentions using Calena in it…

Overall, Canela walks this balance between the warmth of human handwriting and stately details. It makes me think of something literary, which is why I used it for project in one of the new video lessons in Learn UI Design.


Mark Boulton has a cool new site: TypeSpecimens.

Type specimens are curious objects. They aim to inspire designers. They are tools with which to make design decisions. They are also marketing material for foundries. This project will dig into specimens from these three perspectives: as artefacts made by and for font designers to evolve type culture; as tools for font users to make decisions about choosing and using type; and as effective marketing tools.

The post Some Typography Links appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Some Innocent Fun With HTML Video and Progress

The idea came while watching a mandatory training video on bullying in the workplace. I can just hear High School Geoff LOL-ing about a wimp like me have to watch that thing.

But here we are.

The video UI was actually lovely, but it was the progress bar that really caught my attention – or rather the [progress].value. It was a simple gradient going from green to blue that grew as the video continued playing.

If only I had this advice in high school…

I already know it’s possible to create the same sort gradient on the <progress> element. Pankaj Parashar demonstrated that in a CSS-Tricks post back in 2016.

I really wanted to mock up something similar but haven’t played around with video all that much. I’m also no expert in JavaScript. But how hard can that actually be? I mean, all I want to do is get know how far we are in the video and use that to update the progress value. Right?

My inner bully made so much fun of me that I decided to give it a shot. It’s not the most complicated thing in the world, but I had some fun with it and wanted to share how I set it up in this demo.

The markup

HTML5 all the way, baby!

<figure>   <video id="video" src="http://html5videoformatconverter.com/data/images/happyfit2.mp4"></video>   <figcaption>     <button id="play" aria-label="Play" role="button">►</button>     <progress id="progress" max="100" value="0">Progress</progress>     </figcaotion> </figure>

The key line is this:

<progress id="progress" max="100" value="0">Progress</progress>

The max attribute tells us we’re working with 100 as the highest value while the value attribute is starting us out at zero. That makes sense since it allows us to think of the video’s progress in terms of a percentage, where 0% is the start and 100% is the end, and where our initial starting point is 0%.

Styling

I’m definitely not going to get deep into the process of styling the <progress> element in CSS. The Pankaj post I linked up earlier already does a phenomenal job of that. The CSS we need to paint a gradient on the progress value looks like this:

/* Fallback stuff */ progress[value] {   appearance: none; /* Needed for Safari */   border: none; /* Needed for Firefox */   color: #e52e71; /* Fallback to a solid color */ }  /* WebKit styles */ progress[value]::-webkit-progress-value {   background-image: linear-gradient(     to right,     #ff8a00, #e52e71   );   transition: width 1s linear; }  /* Firefox styles */ progress[value]::-moz-progress-bar {   background-image: -moz-linear-gradient(     to right,     #ff8a00, #e52e71   ); }

The trick is to pay attention to the various nuances that make it cross-browser compatible. Both WebKit and Mozilla browsers have their own particular ways of handling progress elements. That makes the styling a little verbose but, hey, what can you do?

Getting the progress value from a video

I knew there would be some math involved if I wanted to get the current time of the video and display it as a value expressed as a percentage. And if you thought that being a nerd in high school gained me mathematical superpowers, well, sorry to disappoint.

I had to write down an outline of what I thought needed to happen:

  • Get the current time of the video. We have to know where the video is at if we want to display it as the progress value.
  • Get the video duration. Knowing the video’s length will help express the current time as a percent.
  • Calculate the progress value. Again, we’re working in percents. My dusty algebra textbook tells me the formula is part / whole = % / 100. In the context of the video, we can re-write that as currentTime / duration = progress value.

That gives us all the marching orders we need to get started. In fact, we can start creating variables for the elements we need to select and figure out which properties we need to work with to fill in the equation.

// Variables const progress = document.getElementById( "progress" );  // Properties // progress.value = The calculated progress value as a percent of 100 // video.currentTime = The current time of the video in seconds // video.duration = The length of the video in seconds

Not bad, not bad. Now we need to calculate the progress value by plugging those things into our equation.

function progressLoop() {   setInterval(function () {     document.getElementById("progress").value = Math.round(       (video.currentTime / video.duration) * 100     );   }); }

I’ll admit: I forgot that the equation would result to decimal values. That’s where Math.round() comes into play to update those to the nearest whole integer.

That actually gets the gradient progress bar to animate as the video plays!

I thought I could call this a win and walk away happy. Buuuut, there were a couple of things bugging me. Plus, I was getting errors in the console. No bueno.

Showing the current time

Not a big deal, but certainly a nice-to-have. We can chuck a timer next to the progress bar and count seconds as we go. We already have the data to do it, so all we need is the markup and to hook it up.

Let’s add a wrap the time in a <label> since the <progress> element can have one.

<figure>   <video controls id="video" src="http://html5videoformatconverter.com/data/images/happyfit2.mp4"></video>   <figcaption>     <label id="timer" for="progress" role="timer"></label>     <progress id="progress" max="100" value="0">Progress</progress>     </figcaotion> </figure>

Now we can hook it up. We’ll assign it a variable and use innerHTML to print the current value inside the label.

const progress = document.getElementById("progress"); const timer = document.getElementById( "timer" );  function progressLoop() {   setInterval(function () {     progress.value = Math.round((video.currentTime / video.duration) * 100);     timer.innerHTML = Math.round(video.currentTime) + " seconds";   }); }  progressLoop();

Hey, that works!

Extra credit would involve converting the timer to display in HH:MM:SS format.

Adding a play button

The fact there there were two UIs going on at the same time sure bugged me. the <video> element has a controls attribute that, when used, shows the video controls, like play, progress, skip, volume, and such. Let’s leave that out.

But that means we need — at the very minimum — to provide a way to start and stop the video. Let’s button that up.

First, add it to the HTML:

<figure>   <video id="video" src="http://html5videoformatconverter.com/data/images/happyfit2.mp4"></video>   <figcaption>     <label id="timer" for="progress" role="timer"></label>     <button id="play" aria-label="Play" role="button">►</button>     <progress id="progress" max="100" value="0">Progress</progress>     </figcaotion> </figure>

Then, hook it up with a function that toggles the video between play and pause on click.

button = document.getElementById( "play" );  function playPause() {    if ( video.paused ) {     video.play();     button.innerHTML = "❙❙";   }   else  {     video.pause();      button.innerHTML = "►";   } }  button.addEventListener( "click", playPause ); video.addEventListener("play", progressLoop);

Hey, it’s still working!

I know it seems weird to take out the rich set of controls that HTML5 offers right out of the box. I probably wouldn’t do that on a real project, but we’re just playing around here.

Cleaning up my ugly spaghetti code

I really want to thank my buddy Neal Fennimore. He took time to look at this with me and offer advice that not only makes the code more legible, but does a much, much better job defining states…

// States const PAUSED = 'paused'; const PLAYING = 'playing';  // Initial state let state = PAUSED;

…doing a proper check for the state before triggering the progress function while listening for the play, pause and click events…

// Animation loop function progressLoop() {   if(state === PLAYING) {     progress.value = Math.round( ( video.currentTime / video.duration ) * 100 );     timer.innerHTML = Math.round( video.currentTime ) + ' seconds';     requestAnimationFrame(progressLoop);   } }  video.addEventListener('play', onPlay); video.addEventListener('pause', onPause); button.addEventListener('click', onClick);

…and even making the animation more performant by replacing setInterval with requestAnimationFrame as you can see highlighted in that same snippet.

Here it is in all its glory!

Oh, and yes: I was working on this while “watching” the training video. And, I aced the quiz at the end, thank you very much. 🤓

The post Some Innocent Fun With HTML Video and Progress appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]