Front End Web Development

CSS Environment Variables

Css Tricks - Fri, 05/04/2018 - 11:05am

We were all introduced to the env() function in CSS when all that drama about "The Notch" and the iPhone X was going down. The way that Apple landed on helping us move content away from those "unsafe" areas was to provide us essentially hard-coded variables to use:

padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);

Uh ok! Weird! Now, nine months later, an "Unofficial Proposal Draft" for env() has landed. This is how specs work, as I understand it. Sometimes browser vendors push forward with stuff they need, and then it's standardized. It's not always waiting around for standards bodies to invent things and then browser vendors implementing those things.

Are environment variables something to get excited about? Heck yeah! In a sense, they are like a more-limited version of CSS Custom Properties, but that means they can be potentially used for more things.

CSS environment variables are getting standardized:
Allow to get and use the browser- and author-defined variables: typography, colors, notch and other specific layout/device values.
They work in Media Queries, where CSS Custom Properties cannot be used.

— Serg Hospodarets (@malyw) April 29, 2018

👀 Brand new spec for global env() variables in CSS:

Forget notches, the important thing here is the ability to separate CSS variables from the cascade. Cool ? for perf/code organization ? because you might be able to use them in media queries!

— Eric Portis (@etportis) April 30, 2018

Eric also points out some very awesome early thinking:

ISSUE 4 - Define the full set of places env() can be used.

  • Should be able to replace any subset of MQ syntax, for example.
  • Should be able to replace selectors, maybe?
  • Should it work on a rule level, so you can insert arbitrary stuff into a rule, like reusing a block of declarations?

Probably still changeable-with-JavaScript as well. I would think the main reason CSS Custom Properties don't work with media queries and selectors and such is because they do work with the cascade, which opens up some very strange infinite loop logic where it makes sense CSS doesn't want to tread.

If you're into the PostCSS thing, there is a plugin! But I'd warn... the same issues that befall preprocessing CSS Custom Properties applies here (except the first one in that article).

The post CSS Environment Variables appeared first on CSS-Tricks.

Inspecting Animations in DevTools

Css Tricks - Fri, 05/04/2018 - 3:57am

I stumbled upon the Animation panel in Chrome’s DevTools the other day and almost jumped out of my seat with pure joy. Not only was I completely unaware that such a thing exists, but it was better than what I could’ve hoped: it lets you control and manipulate CSS animations and visualize how everything works under the hood.

To access the panel, head to More Tools ? Animations in the top right-hand menu when DevTools is open:

Many of the tutorials I found about this were pretty complicated, so let’s take a step back and look at a smaller example to begin with: here’s a demo where the background-color of the html element will transition from black to orange on hover:

html { cursor: pointer; background-color: #333; transition: background-color 4s ease; } html:hover { background-color: #e38810; }

Let’s imagine that we want to nudge that transition time down from 4s. It can get pretty annoying just bumping that number up and down in the element inspector. I typically would’ve opened up DevTools, found the element in the DOM and then ever-so-slowly manipulate it by typing in a value or using the keyboard directional keys. Instead, we can fire up that demo, open DevTools, and switch to the Animation tab which ought to look something like this:

By default, Chrome will be "listening" for animations to take place. Once they do, they’ll be added to the list. See how those animation blocks are displayed sort of like an audio wave? That’s one frame, or act, of an animation and you can see on the timeline above it each frame that follows it. On an animation itself, the inspector will even show us which property is being changed, like background-color or transform. How neat is that?

We can then modify that animation by grabbing that bar and moving it about:

...and it updates the animation right away — no more clicking and editing an animation the old way! Also, you might’ve noticed that hovering over an animation frame will highlight the element that’s being animated in blue. This is handy if you’re editing a complex animation and forget what that crazy weird pseudo element does. If you have multiple animations on a page, then you can see them all listed in that section just like in this demo:

What we’re doing here is animating both the .square and the .circle when hovering on the html element, so there’s effectively two separate divs being animated in the same time frame — that’s why you can see them in the same section just like that.

I can see that inspecting animations in this way could be super useful for tiny icon design, too. Take this pen of Hamburger menu animations by Jesse Couch where you might want to slow everything down to get things just right. Well, with the animation inspector tool you can do exactly that:

Those buttons in the top left-hand corner will control the playback speed of the animation. So hitting 10% will slow things to a crawl — giving you enough time to really futz with things until they’re perfect.

I’ve focused on Chrome here but it’s not the only browser with an animation inspector — Firefox’s tool is in every way just as useful. The only immediate difference I found was that Chrome will listen for any animations on a page and will display them once their captured. But, with Firefox, you have to inspect the element and only then will it show you the animations attached to that element. So, if you’re doing super complex animations, then Chrome’s tool might be a smidge more helpful.

Animation Inspector Documentation

The post Inspecting Animations in DevTools appeared first on CSS-Tricks.

Responsive Knockout Text With Looping Video

Css Tricks - Thu, 05/03/2018 - 4:06am

Here’s an idea! Let’s make an an HTML <video> play inside the shape of some letters. Like "Knockout Text" except instead of an image behind, it’s video. A live demo will explain more clearly:

See the Pen basic pen by Giulio Mainardi (@mgiulio) on CodePen.

A key objective here is to develop this responsively. The idea is to not only scale the video in size to fit the parent container (as video generally does), but scale the text as well, maintaining the size relationship between the type and underlying video.

We’re going to get there by using the CSS clip-path property to clip the video against an SVG path defined within a <clipPath> element.

First we’ll cover the core concept. Then we’ll add some eye candy by adding a few more features and demonstrate them with a couple additional demos.

Setting Up the Video in HTML

Let’s start with the video markup. Inside the <video> tag we specify the URLs for the WebM and MP4 versions of the video, to support a broad range of browsers:

<video> <source src="/video/mt-baker.webm" type="video/webm"> <source src="/video/mt-baker.mp4" type="video/mp4"> </video>

Then we add some attributes to customize the video playing behavior:

<video loop autoplay muted playsinline> <source src="/video/mt-baker.webm" type="video/webm"> <source src="/video/mt-baker.mp4" type="video/mp4"> </video>
  • The loop attribute makes the video plays forever
  • The autoplay and muted attributes are used to allow the automatic video playback at page load on all devices and ensure it play without audio
  • The playsinline attribute tries to disable the full-screen expansion of the video when it is played on some mobile devices

Then a container is wrapped around the <video> element. This will come in handy when we'll spice up the basic demo with some visual effects.

Here’s the complete markup:

<div class="video-container"> <video loop autoplay muted playsinline> <source src="/video/mt-baker.webm" type="video/webm"> <source src="/video/mt-baker.mp4" type="video/mp4"> </video> </div> The Basic CSS to Position and Scale the Video

Here, the main task to fulfill is to make the video responsive. It must scale up and down, spanning the width of its parent container and keeping its intrinsic aspect ratio:

.video-container video { display: block; width: 100%; }

After formatting the video as a block-level element with display: block, assigning a 100% value to its width makes it as large as its container. And that's all we need, because the initial auto value of the height property and the video intrinsic aspect ratio make it uniformly scale, without distortion.

In the original demo, I repeated the video several times in the container to test this responsive behavior. Here’s the CSS I’m using to test the responsiveness of each video at different widths:

.video-container { margin: 40px auto; outline: 1px solid #dadada; &:nth-of-type(1) { width: 25%; } /* first video instance, and so on */ &:nth-of-type(2) { width: 50%; } &:nth-of-type(3) { width: 75%; } &:nth-of-type(4) { width: 100%; } }

The outline set on the containers will help us visualize the location and size of the videos when they are clipped. Speaking of which...

Clipping the Video in CSS

Thanks to the clip-path CSS property, we can define a region of an element to be displayed instead of the entire thing — and do it with a single line:

video { clip-path: url(#clip-00); }

With the url() function, we specify the id of the SVG clipPath element where the clipping text is defined.

Note that although the visible geometry of the video is altered by the clipping, the video element is still a rectangular box for the browser, so the page layout is the same as if the clipping was not used. This is part of the beauty of clipping and, if you’re new to the concept, then definitely check out Sarah’s explanation of it.

Now the trick is actually creating that clip path!

Creating the SVG `clipPath` element

I am going to create the text design, do the editing, then export the work in Inkscape. Similar steps could be put together with other vector editors. Feel free to report your experiences in the comments.

The first step is to keep note of the video aspect ratio, which is its width:height ratio.

Next, create a document with the same size as the video or just with the same aspect ratio. So, for example, if you’re video is 1000px wide and 500px tall, then you could use that as the document size or anything with a 2:1 ratio. This will act as a placeholder for the video, so make sure the document borders are visible. Also, remove the default layer created by the program, as this will simplify the code generated by SVG, avoiding the creation of unnecessary group elements.

Select the text tool, pick a nice bold and thick font, enter the text and stretch it to cover the document rectangle as you please.

Now, if we take a look at the code generated by Inkscape we see something like this:

<text xml:space="preserve" style="font-style:normal;font-weight:normal;font-size:1147.68029785px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" x="23.404421" y="939.04187" id="text3336" sodipodi:linespacing="125%" transform="scale(0.8988993,1.1124717)" > <tspan sodipodi:role="line" id="tspan3338" x="23.404421" y="939.04187" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'" > TEXT </tspan> </text>

That's a bit unwieldy, so let's convert the SVG <text> element into a path:

<g transform="scale(0.8988993,1.1124717)" style="font-style:normal;font-weight:normal;font-size:1147.68029785px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="text3336" > <path d="m 545.68862,31.769213 0,181.566607 -140.09769,0 0,725.70605 -235.92452,0 0,-725.70605 -139.5373,0 0,-181.566607 515.55951,0 z" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'" id="path3348" /> <path d="m 599.48616,31.769213 393.39432,0 0,181.566607 -157.46981,0 0,172.03997 147.38277,0 0,172.60036 -147.38277,0 0,199.49911 173.16073,0 0,181.56661 -409.08524,0 0,-907.272657 z" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'" id="path3350" /> <path d="M 1554.9524,31.769213 1472.575,433.009 l 124.4067,506.03287 -218.5524,0 q -39.2273,-135.61457 -71.73,-330.07016 -8.9662,85.73978 -24.6572,182.127 l -22.4156,147.94316 -229.7602,0 85.1794,-506.03287 -85.1794,-401.239787 228.079,0 q 6.1643,37.546181 24.6572,124.967137 14.5702,66.68651 24.0968,122.16519 l 50.4352,-247.132327 197.8179,0 z" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'" id="path3352" /> <path d="m 2105.8165,31.769213 0,181.566607 -140.0976,0 0,725.70605 -235.9246,0 0,-725.70605 -139.5373,0 0,-181.566607 515.5595,0 z" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-family:Impact;-inkscape-font-specification:'Impact Condensed'" id="path3354" /> </g>

Now, we have a group containing a path element for each letter of the text. Un-grouping it leaves this set of paths at the root level. This step, besides removing the unneeded group, modifies the coordinates of the path elements to account for the transform that was applied to the removed parent group. So, after this step, there are no transform attributes in the SVG:

<path inkscape:connector-curvature="0" id="path3348" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 490.51912,35.34235 0,201.98771 -125.93372,0 0,807.32744 -212.07238,0 0,-807.32744 -125.429984,0 0,-201.98771 463.436084,0 z" /> <path inkscape:connector-curvature="0" id="path3350" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 538.87769,35.34235 353.62188,0 0,201.98771 -141.5495,0 0,191.3896 132.48227,0 0,192.01302 -132.48227,0 0,221.93711 155.65406,0 0,201.98771 -367.72644,0 0,-1009.31515 z" /> <path inkscape:connector-curvature="0" id="path3352" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 1397.7456,35.34235 -74.049,446.36791 111.8291,562.94724 -196.4566,0 q -35.2614,-150.86737 -64.478,-367.19371 -8.0597,95.38308 -22.1644,202.61114 l -20.1493,164.58257 -206.5313,0 76.5677,-562.94724 -76.5677,-446.36791 205.02,0 q 5.5411,41.769064 22.1644,139.0224 13.0971,74.18686 21.6606,135.90532 l 45.3362,-274.92772 177.8183,0 z" /> <path inkscape:connector-curvature="0" id="path3354" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:condensed;font-size:medium;line-height:125%;font-family:Impact;-inkscape-font-specification:'Impact Condensed';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" d="m 1892.917,35.34235 0,201.98771 -125.9337,0 0,807.32744 -212.0724,0 0,-807.32744 -125.43,0 0,-201.98771 463.4361,0 z" />

Those ugly style attributes are still there, but it doesn't matter because we are not going to use them.

We have finished with Inkscape, so we can save the SVG document and open it in our favorite code editor.

Saving SVG files from an illustration application is an art form in and of itself. Here are some common tips and common settings for Adobe Illustrator and a comparison of SVG exports from Illustrator, Sketch and Figma.

In the HTML page where the video is played, insert an inline SVG element. This will host the clip path:

<svg class="clipping-paths"> <defs> </defs> </svg>

We don't want this container element to affect the page layout, so:

.clipping-paths { width: 0; height: 0; position: absolute; }

Add a new clipPath element to the container SVG, with a proper id to identify it in the clip-path property, as seen before:

<svg class="clipping-paths"> <defs> <clipPath id="clip-00"></clipPath> <clipPath id="clip-01"></clipPath> ... </defs> </svg>

As showed in the above snippet, multiple clipping paths can be added, if needed.

Now, we must assign the objectBoundingBox value to the clipPath's attribute clipPathUnits:

<clipPath id="clip-00" clipPathUnits="objectBoundingBox"></clipPath>

This is one of the essential things to do to have a responsive cutout. We tell the browser which coordinate system to use for the numerical values listed in the d attributes of the paths that will be appended to the clipPath element.

The default value for the clipPathUnits attribute is userSpaceOnUse. According to the spec, this means that:

...the contents of the clipPath element represent values in the current user coordinate system in place at the time when the (clipPath)element is referenced (i.e., the user coordinate system for the element referencing the clipPath element via the clip-path property).

Instead, by using the other available value for clipPathUnits, objectBoundingBox, the coordinate values and the lengths specified in the clipPath content are considered as fractional values in the [0,1] range, relative to the bounding box of the clipped element. For instance, if a graphical primitive in the clipPath referred to the coordinates (0,0), (1,0), (1,1), (0,1) and (0.5,0.5), these points would represent respectively, the top left, top right, bottom right, bottom left corners, and the center of the video, no matter the actual size of the video on screen. It is this behavior that allows the text cutout to scale in the same way as the underlying video.

After having removed any transforms from the SVG file in Inkscape, all the numerical values of the path elements are now in the document range. To map them into the [0,1] interval required for objectBoundingBox, it is sufficient to divide such numerical values by the document size. The x coordinates are divided by the document width and the y coordinates by the document height.

To accomplish this division, a scaling with the SVG transform attribute can be employed:

<clipPath id="clip-00" clipPathUnits="objectBoundingBox" transform="scale(0.0005208333333333333, 0.000925925925925926)">

The horizontal scaling must be the reciprocal of the document width, while the vertical scaling must be the reciprocal of the document height. So, in our case, given that the document has the same exact size as the video, that is, 1920 X 1080, we get the two factors 1 / 1920 = 0.0005208333333333333 and 1 / 1080 = 0.000925925925925926.

The last step in this workflow is to copy the <path> elements from the file generated by Inkscape inside the clipPath element, getting something like this:

<clipPath id="clip-00" clipPathUnits="objectBoundingBox" transform="scale(0.0005208333333333333, 0.000925925925925926)"> <path d="m 341.4087,58.040727 0,951.927273 -112.60986,0 -66.8335,-432.74767 0,432.74767 -107.42188,0 0,-951.927273 107.42188,0 72.02149,428.631863 0,-428.631863 107.42187,0 z" /> ... <path d="m 1642.6782,58.040727 214.2334,0 0,190.503053 -85.7544,0 0,180.50751 80.2613,0 0,181.09549 -80.2613,0 0,209.31816 94.2994,0 0,190.50306 -222.7784,0 0,-951.927273 z" /> </clipPath>

To reiterate, we have copied just the d attribute of the paths, discarding all the other stuff generated by Inkscape.

Putting it All Together

And there we have it, gluing together the above snippets with some more code(see the pen source for details), we get the first basic demo:

Other Examples

We can reuse the above workflow to create some more cutouts, like in the second demo here:

The last example is worthy of attention because it is the negative of the text used in the first demo; that is, the internal and external regions delimited by the paths were swapped. So, the white text we see is a hole through which the background color of the page body is visible. This negative cutout was derived from the original with a difference path operation in Inkscape.

Adding Background Colors

Building on top of the basic demo, we can add a color to the text cutout by assigning a background-color to the video container, because this wrapper element is visible everywhere the video is clipped out:

.video-container { // ... &:nth-of-type(1) { background: #c6c7c5; } &:nth-of-type(2) { background: #dcf3ff; } &:nth-of-type(3) { background: #a2d2df; } &:nth-of-type(4) { background: #406e8d; } &:nth-of-type(5) { background: linear-gradient(180deg, #bdc3c2, #2d5d89); } }

The result can be seen in the third demo:

Adding Tint

How about tinting the video? We can do that with a pseudo element and CSS Blend Modes:

.video-container { /* ... */ position: relative; } .video-container::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; clip-path: url(#clip-00); } .video-container:nth-of-type(1) { background: #406e8d; } .video-container:nth-of-type(1)::after { background-color: #3f51b5; mix-blend-mode: screen; }

The ::after pseudo element of the video wrapper is absolutely positioned on top of the video, covering it entirely, and then it is clipped with the same path used for the video. In this way, it is possible to use different colors for the background and the tint.

Finally, after having assigned the desired tint color to the pseudo element, with the mix-blend-mode property we can pick one of the available blending modes to obtain the wanted effect.

Browser Support

At the time of writing, almost all the latest versions of desktop and mobile browsers support the CSS clip-path property. The prefixed version, -webkit-clip-path, has to be used on WebKit-based user agents such as Safari and Samsung Internet.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari695254NoNoTP*Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox11.3*37*No626657

Unfortunately, an exception is given by the Microsoft browsers. There is definitely no support on Internet Explorer, and on Edge the feature is under development. Please vote it up on the Microsoft Developer Feedback page!

Of course, for the last demo, a browser supporting CSS Blend Modes is required. In this case, the support is wider, being this feature is even implemented by Edge.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari301720No136.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox7.0-7.137No4.46657 References and Credits

Eric Meyer writes about the scaling of the SVG clipping path for an HTML element, using the objectBoundingBox value for the clipPathUnits attribute, and the scaling transform. That was a huge inspiration for this post.

Thanks to Coverr for the video that was used in these demos.

The post Responsive Knockout Text With Looping Video appeared first on CSS-Tricks.

?Incapsula DDoS Resiliency Score

Css Tricks - Thu, 05/03/2018 - 4:05am

(This is a sponsored post.)

These free training courses from Incapsula give you the technical knowledge and skills to accelerate your website and optimize content delivery. Website Performance Mastery Starts here in a fun, quiz-based online format, these free training courses give you the technical knowledge and skills to accelerate your website and optimize content delivery.

Is your website ready for a DDoS attack? Find out here.

Direct Link to ArticlePermalink

The post ?Incapsula DDoS Resiliency Score appeared first on CSS-Tricks.

Managing Heading Levels In Design Systems

Css Tricks - Thu, 05/03/2018 - 4:00am

Heydon Pickering looks into how to give a React component a certain heading (like <h1>, <h2>, etc.) depending on its context and thereby ensure that the DOM is still perfectly accessible for screen readers. Why is using the right heading important though? Heydon writes in the intro:

One thing that keeps coming back to me, in research, testing, and everyday conversation with colleagues and friends, is just how important headings are. For screen reader users, headings describe the relationships between sections and subsections and?—?where used correctly?—?provide both an outline and a means of navigation. Headings are infrastructure.

This reminds me of an excellent post by Amelia Bellamy-Royds where she explored all the problems caused by this “Document Outline Dilemma” or, say, a <h1> following a <h3>:

As it currently stands, the document outline is only of daily importance to screen-reader users, and those users are currently used to dealing with the mess of erratic heading levels in web pages. I'm sure many screen-reader users would appreciate heading levels being fixed. But fixing headings for screen-reader users doesn't just mean creating a tree of neatly nested headings with no skipped level numbers. It means creating a heading structure that accurately reflects the meaning intended by the creators of the web page, the meaning that visual users infer from style and layout. And in order to do that, we need to consider how meaning is communicated to all the users of web pages who aren't hearing each heading announced with a numerical level.

It’s remarkable to me that simple ol’ headings require so much attention, both in dealing with the usability concerns and the potential development workarounds.

Direct Link to ArticlePermalink

The post Managing Heading Levels In Design Systems appeared first on CSS-Tricks.

Container-Adapting Tabs With “More” Button

Css Tricks - Wed, 05/02/2018 - 3:51am

Or the priority navigation pattern, or progressively collapsing navigation menu. We can name it in at least three ways.

There are multiple UX solutions for tabs and menus and each of them have their own advantages over another, you just need to pick the best for the case you are trying to solve. At design and development agency Kollegorna we were debating on the most appropriate UX technique for tabs for our client’s website…

We agreed it should be a one-liner because the amount of tab items is unknown and narrowed our options down to two: horizontal scroll and adaptive with “more” button. Firstly, the problem with the former one is that horizontal scroll as a feature is not always visually obvious for users (especially for narrow elements like tabs) whereas what else can be more obvious than a button (“more”), right? Secondly, scrolling horizontally using a mouse-controlled device isn’t a very comfortable thing to do, so we might need to make our UI more complex with additional arrow buttons. All considered, we ended up choosing the later option:


The main intrigue here is if it’s possible to achieve that without JavaScript? Partly yes, however the limitations that it comes with probably make it only good for a concept museum rather than real life scenarios (anyway, Kenan did a really nice job). Still, the dependency on JS doesn’t mean we can’t make it usable if for some reason the technology is not available. Progressive enhancement and graceful degradation for the win!

Since the amount of tab items is uncertain or volatile, we will make use of Flexbox which ensures the items are nicely spread in the container element without setting the widths.

Initial Prototype

There are two lists both visually and technically: one is for items that fit in the container, and one for items that don’t. Since we’ll depend on JavaScript, it’s totally fine to have our initial markup with a single list only (we will duplicate it with JS):

<nav class="tabs"> <ul class="-primary"> <li><a href="...">Falkenberg</a></li> <li><a href="...">Braga</a></li> <!-- ... --> </ul> </nav>

With a tiny touch of flex-based CSS things are starting to get serious here. I’ll skip the decorative CSS properties in my examples here and place here what really matters:

.tabs .-primary { display: flex; } .tabs .-primary > li { flex-grow: 1; }

Here’s what we already have:

Graceful Degradation

Now before enhancing it progressively with JavaScript, let’s make sure it degrades gracefully if there is no JS available. There multiple of reasons for JS absence: it’s still loading, it has fatal errors, it failed to be transferred over the network.

.tabs:not(.--jsfied) { overflow-x: auto; -webkit-overflow-scrolling: touch; }

And once JavaScript is here, the --jsfied class name is added to the container element which neutralizes the CSS above:


Turns out the horizontal scroll strategy that I mentioned before might make a fine use here! When there’s not enough room for menu items the overflowing content gets clipped inside the container and scrollbars are displayed. That’s way better than empty space or something that’s broken, isn’t it?

Missing Parts

First off, let’s insert the missing DOM parts:

  • Secondary (dropdown) list which is a copy of the main list;
  • “More” button.
const container = document.querySelector('.tabs') const primary = container.querySelector('.-primary') const primaryItems = container.querySelectorAll('.-primary > li:not(.-more)') container.classList.add('--jsfied') // insert "more" button and duplicate the list primary.insertAdjacentHTML('beforeend', ` <li class="-more"> <button type="button" aria-haspopup="true" aria-expanded="false"> More &darr; </button> <ul class="-secondary"> ${primary.innerHTML} </ul> </li> `) const secondary = container.querySelector('.-secondary') const secondaryItems = secondary.querySelectorAll('li') const allItems = container.querySelectorAll('li') const moreLi = primary.querySelector('.-more') const moreBtn = moreLi.querySelector('button') moreBtn.addEventListener('click', (e) => { e.preventDefault() container.classList.toggle('--show-secondary') moreBtn.setAttribute('aria-expanded', container.classList.contains('--show-secondary')) })

Here we are nesting secondary list into primary and using some aria-* properties. We want our navigation menu to be accessible, right?

There’s also an event handler attached to the "more" button that toggles the --show-secondary class name on the container element. We’ll use it to show and hide the secondary list. Now let’s style the new parts. You may want to visually accent "more" button.

.tabs { position: relative; } .tabs .-secondary { display: none; position: absolute; top: 100%; right: 0; } .tabs.--show-secondary .-secondary { display: block; }

Here’s where that brought us to:

Obviously, we need some code that hides and shows the tabs…

Hiding and Showing Tabs in the Lists

Because of Flexbox, the tab items will never break into multiple lines and will shrink to their minimum possible widths. This means we can walk through the each item one by one, add up their widths, compare it to the width of .tabs element and toggle the visibility of particular tabs accordingly. For that we will create a function called doAdapt and wrap in the code below in this section.

To begin width, we should visually reveal all the items:

allItems.forEach((item) => { item.classList.remove('--hidden') })

On a side note, .--hidden works the way you’ve probably expected:

.tabs .--hidden { display: none; }

Math time! I’ll have to disappoint you if you expected some advanced mathematics. So, as described previously, we walk through the each primary tab by adding up their widths under stopWidth variable. We also perform a check if the item fits in the container, hide the item if not and save its index for later use.

let stopWidth = moreBtn.offsetWidth let hiddenItems = [] const primaryWidth = primary.offsetWidth primaryItems.forEach((item, i) => { if(primaryWidth >= stopWidth + item.offsetWidth) { stopWidth += item.offsetWidth } else { item.classList.add('--hidden') hiddenItems.push(i) } })

Hereafter, we need to hide the equivalent items from the secondary list that remained visible in the primary one. As well as hide “more” button if no tabs were hidden.

if(!hiddenItems.length) { moreLi.classList.add('--hidden') container.classList.remove('--show-secondary') moreBtn.setAttribute('aria-expanded', false) } else { secondaryItems.forEach((item, i) => { if(!hiddenItems.includes(i)) { item.classList.add('--hidden') } }) }

Finally, ensure doAdapt function is executed at the right moments:

doAdapt() // adapt immediately on load window.addEventListener('resize', doAdapt) // adapt on window resize

Ideally the resize event handler should be debounced to prevent unnecessary calculations.

Ladies and gentlemen, this is the result (play with resizing the demo window):

See the Pen Container-Adapting Tabs With "More" Button by Osvaldas (@osvaldas) on CodePen.

I could probably end my article here, but there is an extra mile we can walk to make it better and some things to note…


It has been implemented in the demo above, but we haven’t overviewed a small detail that improves the UX of our tabs widget. It’s hiding the dropdown list automatically if user clicks anywhere outside the list. For that we can bind a global click listener and check if the clicked element or any of its parents is the secondarylist or "more" button. If not, the dropdown list gets dismissed.

document.addEventListener('click', (e) => { let el = while(el) { if(el === secondary || el === moreBtn) { return; } el = el.parentNode } container.classList.remove('--show-secondary') moreBtn.setAttribute('aria-expanded', false) }) Edge Cases Long Tab Titles

You might have been wondering how the widget behaves with long tab titles. Well, you have at least two options here...

  1. Let titles wrap to the next line which is how they behave by default (you can also enable word wrapping with word-wrap: break-word):
  1. Or you can disable all kinds of wrapping in the primary list with white-space: nowrap. The script is flexible enough to put the too-long items to the dropdown (where the titles are free to wrap) by stepping aside the shorter siblings:
Many Tabs

Even though the secondary list is position: absolute it doesn’t matter how long your document’s height is. As long as the container element or its parents are not position: fixed, the document will adapt and the bottom items will be reachable by scrolling down the page.

A Thing to be Aware Of

Things may become tricky if the tabs are buttons rather than anchors semantically, which means their response to clicks are decided by JavaScript, e.g.: dynamic tabs. The problem here is that tab button event handlers aren’t duplicated along with the markup. I see at least two approaches to solve that:

  • Place dynamic event handler attachments right after the adaptive tab code;
  • Use an event delegation method instead (think of jQuery’s live()).

Unfortunately, events occur in quantity: most likely your tabs will have a selected state that visually indicates the current tab so it’s also important to manage the states simultaneously. Otherwise, flip the tablet and you’re lost.

Browser Compatibility

Even though I used ES6 syntax in the examples and demo, it should be converted to ES5 by a compiler such as Babel to significantly widen the browser support (down to IE9 including).

You can also expand the Flexbox implementation with an older version and syntax (all the way down to IE10). If you need to also support non-Flexbox browsers you can always do feature detection with CSS @supports, apply the technique progressively, and rely on horizontal scroll for older browsers.

Happy tabbing!

The post Container-Adapting Tabs With “More” Button appeared first on CSS-Tricks.

Wakamai Fondue

Css Tricks - Tue, 05/01/2018 - 6:36am

Roel Nieskens released a tool that lets you upload a font file and see what’s inside, from how many characters it contains to the number of languages it supports. Here’s what you see once you upload a font, in this case Covik Sans Mono Black:

Why is this data useful? Well, I used this tool just the other day when I found a font file in a random Dropbox folder. What OpenType features does this font have? Are there any extra glyphs besides the Roman alphabet inside? Wakamai Fondue answered those questions for me in a jiffy.

Direct Link to ArticlePermalink

The post Wakamai Fondue appeared first on CSS-Tricks.

Wakamai Fondue

Css Tricks - Tue, 05/01/2018 - 6:36am

Roel Nieskens released a tool that lets you upload a font file and see what’s inside, from how many characters it contains to the number of languages it supports. Here’s what you see once you upload a font, in this case Covik Sans Mono Black:

Why is this data useful? Well, I used this tool just the other day when I found a font file in a random Dropbox folder. What OpenType features does this font have? Are there any extra glyphs besides the Roman alphabet inside? Wakamai Fondue answered those questions for me in a jiffy.

Direct Link to ArticlePermalink

The post Wakamai Fondue appeared first on CSS-Tricks.

Solved With CSS! Dropdown Menus

Css Tricks - Tue, 05/01/2018 - 3:59am

This post is the second in a series about the power of CSS.

Article Series:
  1. Colorizing SVG Backgrounds
  2. Dropdown Menus (this post)

CSS is getting increasingly powerful, and with features like CSS grid and custom properties (also known as CSS variables), we’re seeing some really creative solutions emerging. Some of those solutions focus around not only making the web prettier, but making it more accessible, and making styling accessible experiences better. I’m definitely here for it!

A common UI pattern that we see on the web are dropdown menus. They’re used to display related information in pieces, without overwhelming the user with buttons, text, and options. Somewhere that we see these a lot is inside of headers or navigation areas on websites.

A Google search for "dropdown menu" yields many examples

Let’s see if we can make one of these menus with CSS alone. We’ll create a list of links within a nav component like so:

<nav role="navigation"> <ul> <li><a href="#">One</a></li> <li><a href="#">Two</a></li> <li><a href="#">Three</a></li> </ul> </nav>

Now, say we want a sub-menu dropdown on the second navigation item. We can do the same thing there and include a list of links within that list item:

<nav role="navigation"> <ul> <li><a href="#">One</a></li> <li><a href="#">Two</a> <ul class="dropdown"> <li><a href="#">Sub-1</a></li> <li><a href="#">Sub-2</a></li> <li><a href="#">Sub-3</a></li> </ul> </li> <li><a href="#">Three</a></li> </ul> </nav>

We now have our two-tiered navigation system. In order to have the content hidden and displayed when we want it to be visible, we’ll need to apply some CSS. All style properties have been removed from the following example for clarity on interaction:

li { display: block; transition-duration: 0.5s; } li:hover { cursor: pointer; } ul li ul { visibility: hidden; opacity: 0; position: absolute; transition: all 0.5s ease; margin-top: 1rem; left: 0; display: none; } ul li:hover > ul, ul li ul:hover { visibility: visible; opacity: 1; display: block; } ul li ul li { clear: both; width: 100%; }

See the Pen Simple CSS Dropdown Menu with Hover by Una Kravets (@una) on CodePen.

Now, the submenu dropdown is hidden, but will be exposed and become visible when we hover over its correlating parent in the navigation bar. By styling ul li ul, we have access to that submenu, and by styling ul li ul li, we have access to the individual list items within it.

The Problem

This is starting to look like what we want, but we’re still far from finished at this point. Web accessibility is a core part of your product's development, and right now would be the perfect opportunity to bring this up. Adding role="navigation" is a good start, but in order for a navigation bar to be accessible, one should be able to tab through it (and focus on the proper item in a sensible order), and also have a screen reader accurately read out loud what is being focused on.

You can hover over any of the list items and clearly see what is being hovered over, but this isn’t true for tab navigation. Go ahead and try to tab through the example above. You lose track of where the focus is visually As you tab to Two in the main menu, you’ll see a focus indicator ring, but when you tab to the next item (one of its submenu items), that focus disappears.

Now, it’s important to note that theoretically you are focused on this other item, and that a screen reader would be able to parse that, reading Sub-One, but keyboard users will not be able to see what’s going on and will lose track.

The reason this happens is because, while we’re styling the hover of the parent element, as soon as we transition focus from the parent to one of the list items within that parent, we lose that styling. This makes sense from a CSS standpoint, but it’s not what we want.

Luckily, there is a new CSS pseudo class that will give us exactly what we want in this case, and it’s called :focus-within.

The Solution: `:focus-within`

The :focus-within pseudo selector is a part of the CSS Selectors Level 4 Spec and tells the browser to apply a style to a parent when any of its children are in focus. So in our case, this means that we can tab to Sub-One and apply a :focus-within style along with the :hover style of the parent and see exactly where we are in the navigation dropdown. In our case it would be ul li:focus-within > ul:

ul li:hover > ul, ul li:focus-within > ul, ul li ul:hover { visibility: visible; opacity: 1; display: block; }

See the Pen Simple CSS Dropdown Menu with Hover and :focus-within by Una Kravets (@una) on CodePen.

Sweet! It works!

Now, when we tab to the second item, our submenu pops up, and as we tab through the submenu, the visibility remains! Now, we can append our code to include :focus states alongside :hover to give keyboard users the same experience as our mouse users.

In most cases, such as on direct links, we usually can just write something like:

a:hover, a:focus { ... }

But in this case, since we’re applying hover styles based on the parent li, we can again utilize :focus-within to get the same look at feel when tabbing through. This is because we can’t actually focus on the li (unless we add a tabindex="0"). We’re actually focusing on the link (a) within it. :focus-within allows us to still apply styles to the parent li when focusing on the link (pretty darn cool!):

li:hover, li:focus-within { ... }

At this point, since we are applying a focus style, we can do something that’s typically not recommended (remove the styling of that blue outline focus ring). We can do this by:

li:focus-within a { outline: none; }

The above code specifies that when we focus within list items via the link (a), do not apply an outline to the link item (a). It’s pretty safe to write it this way, because we’re exclusively styling the hover state, and with browsers that do not support :focus-within, the link will still get a focus ring. Now our menu looks like this:

Final menu using :focus-within, :hover states, and customizing the focus ring to disappear

See the Pen Simple CSS Dropdown Menu with Hover and :focus-within and Focus states by Una Kravets (@una) on CodePen.

What About ARIA?

If you’re familiar with accessibility, you may have heard of ARIA labels and states. You can use these to your advantage to also create these types of dropdowns with built-in accessibility at the same time! You can find an excellent example here by Heydon Pickering. When including ARIA markup, your code would look a little more like this:

<nav role="navigation"> <ul> <li><a href="#">One</a></li> <li><a href="#" aria-haspopup="true">Two</a> <ul class="dropdown" aria-label="submenu"> <li><a href="#">Sub-1</a></li> <li><a href="#">Sub-2</a></li> <li><a href="#">Sub-3</a></li> </ul> </li> <li><a href="#">Three</a></li> </ul> </nav>

You’re adding aria-haspopup="true" to the parent of the dropdown menu to indicate an alternative state, and including aria-label="submenu" on the actual dropdown menu itself (in this case our list with class="dropdown".

These properties themselves will give you the functionality you need to show the dropdown menu, but the downside is that they only work with JavaScript enabled.

Browser Support Caveat

Speaking of caveats, let’s talk about browser support. While :focus-within does have pretty good browser support, it’s important to note that Internet Explorer and Edge are not supported, so your users on those platforms will not be able to see the navigation.

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari604752NoNo10.1Mobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid Firefox10.3NoNoNo6657

The ultimate solution here would be to use both ARIA markup and CSS :focus-within to ensure a solid dropdown experience for your users.

See the Pen Simple CSS Dropdown Menu with Hover and :focus-within and Focus states and ARIA by Una Kravets (@una) on CodePen.

If you want to be able to use this feature in the future, please upvote it on Edge User Voice! And upvote :focus-ring while you’re at it, so that we’ll be able to style that focus ring and create a beautiful interactive web experience for all &#x1f600;

More on `:focus-within` and A11Y

The post Solved With CSS! Dropdown Menus appeared first on CSS-Tricks.

Animating Progress

Css Tricks - Mon, 04/30/2018 - 10:34am

Jonathan Snook on the complexity of animating the <progress> element. If you’re unfamiliar, that’s the element that spits out a bar chart-like visual that indicates a position between two values:

This example has custom styles, but you get the point.

Jonathan's post shows off a method for animating a change in progress value using CSS and a touch of JavaScript while making sure that it animates properly in every modern browser. The demo he made looks pretty neat. I’m sure this is going to be one of those posts I come back to again and again.

We recently shared a post by Dave Rupert that takes an SVG approach. Jeremias Menichelli also has an alternative approach, creating a ring shape and converting it into a React component.

Direct Link to ArticlePermalink

The post Animating Progress appeared first on CSS-Tricks.

Finger-friendly numerical inputs with `inputmode`

Css Tricks - Mon, 04/30/2018 - 3:49am

Forms are often a nightmare on mobile. We can make the process as pain-free as possible by reacting to context. Input fields that expect numerical values should have a numerical UI. Bringing up a number keyboard on small screens is easy on most platforms — just use a <input type="number">.

This big button numeric keyboard is finger-friendly and will help prevent users bouncing from your form in frustration. However, type="number" isn’t appropriate for all numbers.

On (most) larger screens, number inputs come with an incrementer/decrementer button. It’s a useful piece of UI we get for free by default. It does, however, make this kind of input totally inappropriate for a credit card number, for example.

The default UI for number inputs looks something like this in all desktop browsers

The spec itself makes this clear.

The type=number state is not appropriate for input that happens to only consist of numbers but isn’t strictly speaking a number. For example, it would be inappropriate for credit card numbers or US postal codes. A simple way of determining whether to use type=number is to consider whether it would make sense for the input control to have a spinbox interface (e.g., with "up" and "down" arrows). Getting a credit card number wrong by 1 in the last digit isn’t a minor mistake, it’s as wrong as getting every digit incorrect. So it would not make sense for the user to select a credit card number using "up" and "down" buttons. When a spinbox interface is not appropriate, type=text is probably the right choice (possibly with a pattern attribute).

It’s easy to hide the up and down buttons with CSS:

input[type="number"] { -moz-appearance: textfield; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

It’s important to note that this isn’t the only difference between a number and text input. You should definitely follow the spec on this point! Some older browsers will strip out leading zeros for number inputs which would be a big problem for US ZIP codes. The often-useful maxlength attribute is ignored on number inputs.

yes yes yes! <input type=number> can finally die the fiery death it deserves!

— Monica Dinculescu (@notwaldorf) March 13, 2018

Why would anybody dislike such a useful input?

The answer comes down to validation and using the input for the wrong thing. The number input performs input sanitization by default. If a user enters anything that isn’t a valid number, the value will be equal to an empty string — regardless of what the user can see on the screen.

This input sanitization can trip developers up, and there’s no way to turn it off. If you want to allow input that isn’t a valid number, don’t use type="number".

Number input in Chrome. This might be valid input for your use case, but it’s illegitimate in the eyes of the number input. var numberinput = document.querySelector('input[type="number"]') numberinput.value // will be ""

This might not be what you would intuitively expect. However, if you follow the spec and only use the number input for what its designed for — actual numbers — this behavior is unproblematic.

Number Input Alternatives iOS Solution: Use the `pattern` Attribute on a Text Input

On iOS devices, using the pattern attribute with a value of [0-9]* will bring up the numeric keypad. This only works with this exact pattern — you can’t allow any extra characters.

<label for="creditcard">credit card number:</label> <input pattern="[0-9]*" type="text" name="creditcard"> iOS with pattern attribute

Bear in mind that an iPhone won’t let the user switch keyboard type when this keyboard is displayed. Make sure these are the only keys they need to fill in the input correctly.

If you want to bring up a keypad of large numeric keys on iOS, you need to use the pattern attribute even on number inputs. Otherwise, you’ll get small and finger-friendly buttons:

iOS keypad for <input type="number"> A Better Solution: `inputmode`

inputmode has been a WHATWG spec for a couple of years, and has finally been implemented by Chrome as of version 66:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

DesktopChromeOperaFirefoxIEEdgeSafari66No20NoNoNoMobile / TabletiOS SafariOpera MobileOpera MiniAndroidAndroid ChromeAndroid FirefoxNoNoNoNoNoNo

For the widest support possible, it can be combined with the pattern attribute for iOS:

<label for="creditcard">credit card number:</label> <input inputmode="numeric" pattern="[0-9]*" type="text" name="creditcard">

This gives developers full control of the mobile UI without any extra baggage. It makes the UI finger-friendly while being more versatile than the pattern attribute as we can allow any characters we like. It controls one thing — and one thing only. inputmode is a great solution for those cases when it's inappropriate to use type="number".

Some people would go further and ditch type="number" altogether once inputmode has better support. I’m not convinced that’s wise, but type="number" can be problematic.

if (numberInput.validity.valueMissing) { errorMessage.textContent = "field must not be empty" } Contrary to the human eye, the field is empty...

If you want to explicitly warn of empty number inputs, you’ll need to use:

if (numberInput.validity.valueMissing && !numberInput.validity.badInput) { errorMessage.textContent = "field must not be empty" }

According to Google, users abandon purchases twice as often on mobile as compared to desktop. Sales on phones account for only one third of all completed online purchases. Clearly people don’t tolerate fumbling through badly designed forms and jabbing at tiny inputs. Data entry needs to be effortless. While browser support is currently low, we're only really waiting on mobile browsers. Desktop support is largely irrelevant. The input elements introduced by HTML5 are great, but they miss some edge cases. This can fill in some gaps.

The post Finger-friendly numerical inputs with `inputmode` appeared first on CSS-Tricks.

Practical Jokes in the Browser

Css Tricks - Sat, 04/28/2018 - 3:03am

I know April Fool’s Day is at the beginning of this month, but hey, now you’ve got a year to prepare. Not to mention a gool ol’ practical joke can be done anytime.

Fair warning on this stuff… you gotta be tasteful. Putting someone’s stapler in the jello is pretty hilarious unless it’s somehow a family heirloom, or it’s someone who’s been the target of a little too much office prankery to the point it isn’t funny anymore. Do good. Have fun.

setTimeout(function() { var text = new SpeechSynthesisUtterance("LOLOLOLOLOLOLOLOL"); speechSynthesis.speak(text); }, 600000);

Direct Link to ArticlePermalink

The post Practical Jokes in the Browser appeared first on CSS-Tricks.

Fonts for your finals: New on Typekit for May

Nice Web Type - Fri, 04/27/2018 - 12:30pm

It’s hard to believe we’re already at the end of April — but here we are, and we’ve got more new type in the library to share with you. Have a look at what we’ve added this past month and a few other things that we’ve had going on.

Jamie Clarke Type

Rig Solid from Jamie Clarke Type

We love the bold, fresh type from designer Jamie Clarke, full of energy and fantastic for display. His Rig Shaded recently won the Platinum award in the Graphis competition for typography. Rig Shaded and its sibling Rig Solid are both available in a stunning variety of styles that can be layered on top of one another for shadow effects, outlines, gradients, and more.

Brim Narrow

Brim Narrow offers a similar variety of layering options but with a decidedly different style featuring stately serifs. Use Brim Narrow Combined for simplicity if you’re working with just one color or want the fonts on your website (although it is possible to combine layers using CSS!).

Production Type

Countach from Production Type

We added several Production Type families from Jean-Baptiste Levée and his team to our subscription library. Countach is one of these — originally designed for a car racing game, with an emphatic italic style that exhibits a clear velocity and an extended character set including a well-rounded Cyrillic.

Panorama Extended (left) and Semicondensed (right)

Once in a while a type family just keeps growing and growing over the years, and Production Type’s Panorama collection is such an example. Six widths and eight weights, plus italics, make for a whopping 96 font styles for this family. The variety makes this an especially adaptable choice for all manner of projects. We’ve added the whole shebang to our Marketplace: Panorama Regular as well as Semi Condensed, Condensed, Extra Condensed, Extended, and Extra Extended.

See everything from Production Type on their foundry page.

New from Device Fonts

Urbane Rounded from Device Fonts

Urbane Rounded comes to us from Rian Hughes of Device Fonts. It’s a cheerful rounded sans with seven weights, and will easily lighten the mood where it’s used — the heaviest weight in particular is nearly balloon-like, in the best way possible. Use the lighter weights where more subtlety is needed, like in site navigation or smaller text.

Rogue Serif

Rogue Serif has a hearty personality like many slab serifs, perhaps with a slight edginess from the sharply-carved sides and terminals. If you’re going with a lighter weight it’s perfectly lovely for body text, but less is more when it comes to the heavier weights — size it up, trim your copy, and give the letters plenty of space to shine.

There’s more from Device this month, too; have a look over on the foundry page for the full collection.

Adobe Type news

Taro Yamamoto accepting the Keinosuke Sato award (left) and joining a panel discussion with fellow winner Akira Kobayashi and moderator Kiyonori Muroga.

The Japan Typography Association selected Adobe as the 2017 company winner of the Keinosuke Sato award, which is given to a selected company and individual each year for meaningful contributions to Japanese typography. Taro Yamamoto accepted the award on behalf of Adobe Type on April 20 in Tokyo.

We also celebrated the first anniversary since Source Han Serif‘s release, and added Ten Mincho to our free tier. Oh, and how was your Font Day this year?

Conference season ramping up

It’s getting to be that time of the year when everyone seems to be traveling. In case you missed our speaking event roundup earlier in the spring, here’s a few upcoming highlights:

  • Dan Rhatigan presents at HOW Design Live on May 2
  • Computer Scientist Persa Zula will speak at !!Con in New York on May 12
  • There’s still time to register for the 2018 Ampersand Conference in Brighton! Dan will be speaking there, too. (PS: Use code ADOBE10 when you register for 10% off the ticket price.)

CSS Blocks

Css Tricks - Fri, 04/27/2018 - 5:10am

A new entry into the CSS-in-JS landscape! Looks like the idea is that you write an individual CSS file for every component. You have to work in components, that's how the whole thing works. In the same isle as styled-components, css-modules, and glamorous.

Then you write :scope { } which is the base style for that component. Which I guess means you get out of having to pick a name! But also means you're pretty locked in (true with just about any style processing setup).

Then both the CSS and component are compiled, and probably optimized with its partner tool OptiCSS. The end result is super optimized styles. Since it's "template aware", the styles can be far more optimized than they could be by any system trying to optimize CSS in isolation.

Chris Eppstein:

With CSS Blocks, and OptiCSS running at its core, you get to write ergonomic CSS and let the build take care of making your stylesheets properly scoped, screaming fast, and fantastically small.

Speed, style scoping, and never/rarely having unsued CSS definitely seem like the big benefits to me. A non-trivial thing to move to, but sounds like it could be worth it for plenty of big sites and new sites.

A couple of setup repos to explore to see how it could work: css-blocks-webpack-3 and css-blocks-hello-world.

Direct Link to ArticlePermalink

The post CSS Blocks appeared first on CSS-Tricks.

Updates to CC Libraries bring type to more places

Nice Web Type - Thu, 04/26/2018 - 10:39am

When CC Libraries makes an update that loops fonts into more products, we’re thrilled! Bridging apps and devices alike, CC Libraries plays a fundamental role connecting Adobe applications with one another so your best ideas and creative assets are where you need them, when you need them.

Today’s update works in tandem with Adobe Capture, a mobile app that helps you turn creative inspiration from the world around you into patterns, vector shapes, 3D materials, color themes, brushes, and type that you can then go on to use in your projects.

The technology for Type Capture is shared with the visual search feature we released last autumn. With this update, your typographic options now include fonts available for purchase from Typekit Marketplace (as well as everything in our subscription library).

Starting in Adobe Capture, snap a photo of type and the app will identify similar fonts from Typekit. Choose your favorite and save it as a character style.

How this works

When you see type you like (say, on an eye-catching poster you pass every day), use Capture to snap a photo of it. The Capture app finds similar fonts from Typekit, and you can save your favourites as CC Libraries character styles. If there’s already a Library going for the project you’re working on — maybe you’ve been searching for logo ideas for a new website, for example — go ahead and save it there.

When you’re ready to begin working with the fonts you’ve found, make sure you’re signed in to the CC desktop app so that we can send them your way. Whether you’re working in InDesign, Illustrator, Photoshop, or another design application that displays the CC Libraries panel, fonts from our subscription library will sync automatically at this point.

Want a quick walkthrough? See the Capture tutorial for a one-minute look at how it all comes together.

Purchasing fonts: The new (in-app!) way

For any fonts from Typekit Marketplace, you’ll see this nifty new window to authorize and process a purchase in-app.

When you’re ready to work with the text in your design, the character styles you’ve saved will be in the CC Libraries panel. Fonts requiring a Typekit Marketplace purchase will use the credit card info you have on file; simply approve the purchase from within the app.

If this is your first purchase, we’ll bring you to a secure browser window to enter your credit card information. That’s the one time we’ll interrupt you; after that, we’ll keep the card information on file so you’ll be able to authorize future font purchases without leaving the app you’re in.

Fonts you purchase on Marketplace are synced through the CC desktop app and can be used in any application. You won’t need to install anything via font management software. Just keep the CC desktop app running and it’s smooth sailing from there.

Any questions? Drop a comment here, or send an email to our awesome support team, and we’ll be happy to help you out.

Radial Gradient Recipes

Css Tricks - Thu, 04/26/2018 - 4:01am

Radial gradients are pretty dang cool. It's amazing we can paint the background of an element with them so easily. Easily is a relative term though. It's certainly easier than needing to create a graphic in third-party software to use as the background, and the syntax is highly learnable. But it's also not that easy to remember if you don't use it often, and it's more complicated than linear-gradient().

I figured I'd put together a page of reference examples, so if you know what you need but forget the syntax, it's easy to find that starter code example here.

Centered Bursts

The simplest possible syntax places the first color in the center of the element and the second color on the outside and that's that:

See the Pen Radial Gradient - Centered by Chris Coyier (@chriscoyier) on CodePen.

That will stretch the gradient into an ellipse on a non-square element though. If you don't like that, you can force the shape into a circle, like the second example here demonstrates:

See the Pen Radial Gradient - Circle vs. Ellipse by Chris Coyier (@chriscoyier) on CodePen.

You can also control the size by literally saying how large the circle/ellipse should be (the final color will still stretch to cover the element) by:

  • Using a keyword closest-side, farthest-side, closest-corner, farthest-corner
  • Explicitly saying like radial-gradient(circle 100px, ...)
  • Using color stops like radial-gradient(#56ab2f, #a8e063 150px)

See the Pen Radial Gradient - Sizing by Chris Coyier (@chriscoyier) on CodePen.

Here's some of that stuff in use:

See the Pen Usage of Radial Gradients by Chris Coyier (@chriscoyier) on CodePen.

See the Pen Lit text by Chris Coyier (@chriscoyier) on CodePen.


Besides controlling the size and shape of the gradient, the other big trick to know with radial gradients is that you can position the center of them.

This is one of the shortcomings, I find, with gradient generators. They help you pick colors and color stops and stuff, but they usually punt on the positioning stuff.

This is a beautiful gradient tool, but doesn't help with positioning or sizing. Some of them do help a little with positioning (see "Expert" settings), but don't expose all the possibilities.

The center of a radial gradient doesn't have to be in the center! For example, you can position the center in the top left like this:

.element { background: radial-gradient( at top left, var(--light), var(--dark) /* using variables just for fun! */ ) }

Here's all the four corners:

See the Pen Positioned Radial Gradients by Chris Coyier (@chriscoyier) on CodePen.

You can also be very specifically positioned. Here's an example of a gradient positioned exactly 195px from the left along the bottom of the element. It also has a specific size, but otherwise does the default ellipse shape:

.element { background: radial-gradient( 150px 40px at 195px bottom, #666, #222 ); }

See the Pen Specifically positioned gradient by Chris Coyier (@chriscoyier) on CodePen.

Another little thing to know is that you can use transparent in the gradients to expose the color behind if that's needed, or partially transparent colors like rgba(255, 255, 255, 0.5) to do the same at a colorized color stop.

Also, radial gradients can be used with multiple backgrounds, applying multiple of them to a single element, even overlapping!

.element { background: radial-gradient( circle at top left, rgba(255, 255, 255, 0.5), transparent 100px ), radial-gradient( circle at top right, rgba(255, 255, 255, 0.5), transparent 100px ), radial-gradient( at bottom left, rgba(255, 0, 255, 0.5), transparent 400px ), radial-gradient( at bottom right, rgba(255, 100, 100, 0.5), transparent 400px ); }

See the Pen Multiple Gradients by Chris Coyier (@chriscoyier) on CodePen.

To highlight the idea that the center of the gradient can be anywhere, here's a gradient that follows the mouse:

See the Pen Radial Gradient Move With Mouse by Leo Sammarco (@lsammarco) on CodePen.


People tend to think about browser support, and rightfully so, but don't think too hard about it in this case. We're at pretty much across the board support even without any prefixes.

OK bye!

See the Pen CSS Sunset Sunrise by Marty Saetre (@msaetre) on CodePen.

The post Radial Gradient Recipes appeared first on CSS-Tricks.

?Level Up Your JavaScript Error Monitoring

Css Tricks - Thu, 04/26/2018 - 4:00am

(This is a sponsored post.)

Automatically detect and diagnose JavaScript errors impacting your users with Bugsnag without changing your code or adding try/catch blocks. Get comprehensive diagnostic reports, know immediately which errors are worth fixing, and debug in a fraction of the time compared to traditional tools.

Bugsnag detects every single error and prioritizes errors with the greatest impact on your users. Get support for 50+ platforms and integrate with the development and productivity tools your team already uses.

Bugsnag is used by the world's top engineering teams including Airbnb, Lyft, Square, Yelp, Eventbrite, Shopify, MailChimp, and Docker. Start your free trial today.

Direct Link to ArticlePermalink

The post ?Level Up Your JavaScript Error Monitoring appeared first on CSS-Tricks.

Understanding React `setState`

Css Tricks - Wed, 04/25/2018 - 3:36am

React components can, and often do, have state. State can be anything, but think of things like whether a user is logged in or not and displaying the correct username based on which account is active. Or an array of blog posts. Or if a modal is open or not and which tab within it is active.

React components with state render UI based on that state. When the state of components changes, so does the component UI.

That makes understanding when and how to change the state of your component important. At the end of this tutorial, you should know how setState works, and be able to avoid common pitfalls that many of us hit when when learning React.

Workings of `setState()`

setState() is the only legitimate way to update state after the initial state setup. Let’s say we have a search component and want to display the search term a user submits.

Here’s the setup:

import React, { Component } from 'react' class Search extends Component { constructor(props) { super(props) state = { searchTerm: '' } } }

We’re passing an empty string as a value and, to update the state of searchTerm, we have to call setState().

setState({ searchTerm: })

Here, we’re passing an object to setState(). The object contains the part of the state we want to update which, in this case, is the value of searchTerm. React takes this value and merges it into the object that needs it. It’s sort of like the Search component asks what it should use for the value of searchTerm and setState() responds with an answer.

This is basically kicking off a process that React calls reconciliation. The reconciliation process is the way React updates the DOM, by making changes to the component based on the change in state. When the request to setState() is triggered, React creates a new tree containing the reactive elements in the component (along with the updated state). This tree is used to figure out how the Search component’s UI should change in response to the state change by comparing it with the elements of the previous tree. React knows which changes to implement and will only update the parts of the DOM where necessary. This is why React is fast.

That sounds like a lot, but to sum up the flow:

  • We have a search component that displays a search term
  • That search term is currently empty
  • The user submits a search term
  • That term is captured and stored by setState as a value
  • Reconciliation takes place and React notices the change in value
  • React instructs the search component to update the value and the search term is merged in

The reconciliation process does not necessarily change the entire tree, except in a situation where the root of the tree is changed like this:

// old <div> <Search /> </div> // new <span> <Search /> </span>

All <div> tags become <span> tags and the whole component tree will be updated as a result.

The rule of thumb is to never mutate state directly. Always use setState() to change state. Modifying state directly, like the snippet below will not cause the component to re-render.

// do not do this this.state = { searchTerm: } Passing a Function to `setState()`

To demonstrate this idea further, let's create a simple counter that increments and decrements on click.

See the Pen setState Pen by Kingsley Silas Chijioke (@kinsomicrote) on CodePen.

Let’s register the component and define the markup for the UI:

class App extends React.Component { state = { count: 0 } handleIncrement = () => { this.setState({ count: this.state.count + 1 }) } handleDecrement = () => { this.setState({ count: this.state.count - 1 }) } render() { return ( <div> <div> {this.state.count} </div> <button onClick={this.handleIncrement}>Increment by 1</button> <button onClick={this.handleDecrement}>Decrement by 1</button> </div> ) } }

At this point, the counter simply increments or decrements the count by 1 on each click.

But what if we wanted to increment or decrement by 3 instead? We could try to call setState() three times in the handleDecrement and handleIncrement functions like this:

handleIncrement = () => { this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) } handleDecrement = () => { this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) this.setState({ count: this.state.count - 1 }) }

If you are coding along at home, you might be surprised to find that doesn’t work.

The above code snippet is equivalent to:

Object.assign( {}, { count: this.state.count + 1 }, { count: this.state.count + 1 }, { count: this.state.count + 1 }, )

Object.assign() is used to copy data from a source object to a target object. If the data being copied from the source to the target all have same keys, like in our example, the last object wins. Here's a simpler version of how Object.assign() works;

let count = 3 const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3} ); console.log(object); // output: Object { count: 6 }

So instead of the call happening three times, it happens just once. This can be fixed by passing a function to setState(). Just as you pass objects to setState(), you can also pass functions, and that is the way out of the situation above.

If we edit the handleIncrement function to look like this:

handleIncrement = () => { this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) this.setState((prevState) => ({ count: prevState.count + 1 })) }

...we can now increment count three times with one click.

In this case, instead of merging, React queues the function calls in the order they are made and updates the entire state ones it is done. This updates the state of count to 3 instead of 1.

Access Previous State Using Updater

When building React applications, there are times when you'll want to calculate state based the component’s previous state. You cannot always trust this.state to hold the correct state immediately after calling setState(), as it is always equal to the state rendered on the screen.

Let's go back to our counter example to see how this works. Let's say we have a function that decrements our count by 1. This function looks like this:

changeCount = () => { this.setState({ count: this.state.count - 1}) }

What we want is the ability to decrement by 3. The changeCount() function is called three times in a function that handles the click event, like this.

handleDecrement = () => { this.changeCount() this.changeCount() this.changeCount() }

Each time the button to decrement is clicked, the count will decrement by 1 instead of 3. This is because the this.state.count does not get updated until the component has been re-rendered. The solution is to use an updater. An updater allows you access the current state and put it to use immediately to update other items. So the changeCount() function will look like this.

changeCount = () => { this.setState((prevState) => { return { count: prevState.count - 1} }) }

Now we are not depending on the result of this.state. The states of count are built on each other so we are able to access the correct state which changes with each call to changeCount().

setState() should be treated asynchronously — in other words, do not always expect that the state has changed after calling setState().

Wrapping Up

When working with setState(), these are the major things you should know:

  • Update to a component state should be done using setState()
  • You can pass an object or a function to setState()
  • Pass a function when you can to update state multiple times
  • Do not depend on this.state immediately after calling setState() and make use of the updater function instead.

The post Understanding React `setState` appeared first on CSS-Tricks.

Grid to Flex

Css Tricks - Tue, 04/24/2018 - 11:04am

Una Kravets shows how to make layouts in CSS Grid with flexbox fallbacks for browsers that don’t support those grid properties just yet. Una writes:

CSS grid is AMAZING! However, if you need to support users of IE11 and below, or Edge 15 and below, grid won't really work as you expect...This site is a solution for you so you can start to progressively enhance without fear!

The site is a provides examples using common layouts and component patterns, including code snippets. For example:

See the Pen Grid To Flex -- Example 1 by Una Kravets (@una) on CodePen.

Direct Link to ArticlePermalink

The post Grid to Flex appeared first on CSS-Tricks.

JAMstack Comments

Css Tricks - Tue, 04/24/2018 - 7:30am

JAMstack sites are often seen as being static. A more accurate mental model for them would be that they are sites which have the ability to be hosted statically. The difference might seem semantic, but thanks to the rise of many tools and services which simplify running a build and deploying to static hosting infrastructure, such sites can feel much fresher and dynamic than you might imagine, while still capable of being served from static hosting infrastructure, with all the benefits that brings.

A feature often used as an example of why a site cannot be hosted statically is comments. A comments engine needs to handle submissions, allow for moderation, and is by its very nature, "dynamic".

Comment systems are generally thought of as quite dynamic content

Thanks to the growing ecosystem of tools available for JAMstack sites, there are solutions to this. Let's look at an example which you could use on your own site, which:

  • Does not depend on client-side JavaScript
  • Could work with any static site generator
  • Includes moderation
  • Sends notifications when new comments need moderating
  • Bakes the comments into your site, so that they load quickly and appear in searches

This example makes use of some of the features of Netlify, a platform for automating, deploying and hosting web projects, but many of the principles could be used with other platforms.

You can see the example site here.

Stashing our content

We'll create 2 forms to receive all of our comments at the different stages of their journey from commenter to content. When Netlify sees a <form>, it creates a unique data store for the data the form collects. We'll make great use of that.

  • Form 1) A queue to hold all of the new comment submissions. In other words, a store to hold all comments awaiting moderation.
  • Form 2) Contains all approved comments.

The act of moderation will be somebody looking at each new submission and deciding, "yep!" or "nope!". Those that get nope-d will be deleted from the queue. Those that are approved will be posted over to the approved comments form.

All of the comments in the approved comments form are used by our static site generator in subsequent site builds thanks to the API access Netlify gives to the submissions in our forms.

The comment form

Each page includes an HTML <form>. By adding the boolean attribute of netlify to any HTML form element in your site, Netlify will automatically generate an API for your form, and gathers all of the submissions to it for you. You'll also be able to access the submissions via that API later. Handy!

The comments <form> on each page will look a lot like this (some classes and extra copy omitted for clarity):

<form netlify name="comments-queue" action="/thanks"> <input name="path" type="hidden" value="{{ page.url }}"> <p> <label for="name">Your name</label> <input type="text" name="name" id="name"> </p> <p> <label for="email">Your email</label> <input type="email" name="email" id="email"> </p> <p> <label for="comment">Your comment</label> <textarea name="comment" id="comment"></textarea> </p> <p> <button type="submit">Post your comment</button> </p> </form>

You'll may notice that the form also includes a type="hidden" field to let us know which page on the site this comment is for. Our static site generator populates that for us when the site is generated, and well use it later when deciding which comments should be shown on which page.

Submissions and notifications

When a new comment is posted via the comment form, Netlify not only stashes that for us, but can also send a notification. That could be:

  • an email
  • a Slack notification
  • a webhook of our choosing.

These give us the chance to automate things a little.

New submissions result in a notification being posted to Slack. We'll get to see what was submitted and to which page right there in our Slack client.

To make things extra slick, we can massage that notification a little to include some action buttons. One button to delete the comment, one to approve it. Approving a new comment from a Slack notification on your phone while riding the bus feels good.

We can't make those buttons work without running a little bit of logic which, we can do in a Lambda function. Netlify recently added support for Lambda functions too, making the process of writing and deploying Lambdas part of the same deployment process. You'll not need to go rummaging around in Amazon's AWS configuration settings.

We'll use one Lambda function to add some buttons to our Slack notification, and another Lambda function to handle the actions of clicking either of those buttons.

Bring the comments into the site

With a freshly approved comment being posted to our approved comments form, we are back to using the submission event triggers that Netlify provides. Every time something is posted to the approved comments form, we'll want to include it in the site, so we have Netlify automatically rebuild and deploy our site.

Most static site generators have some notion of data files. Jekyll uses files in a [_data] directory, Hugo has a similar data directory. This example is using Eleventy as its static site generator which has a similar concept. We'll make use of this.

Each time we run our site build, whether in our local development environment or within Netlify through their automated builds, the first step is to pull all of our external data into local data files which our SSG can then use. We do that with a Gulp task.

Armed with a `comments.json` file which we have populated from a call to Netlify's form submission API which grabbed all of our approved comments, our SSG can now build the site as normal and bake the correct comments right into the HTML of our pages.

Some benefits

Well that was fun, but why bother?

Yes, you could use something like Disqus to add comments to a statically hosted site via a few lines of JavaScript. But that adds an external JavaScript dependency and results in the comments about your content living far away from the content itself. And it's only available once the JavaScript has loaded, pulled in the data and then injected it into your site.

Whereas this method results in comments that are baked right into the content of your site. They'll show up in searches on Google and they will load as part of your site without the need for any client-side JavaScript.

Even better, they'll be available for you to commit right into your code repository with the rest of your content, giving you more peace of mind and portability in the future.

The example site and all of its code are available to explore. You can try submitting comments if you like (although poor old Phil will need to moderate any comments on this example site before they appear, but that will just make him feel loved).

Better still, you can clone this example and deploy your own version to Netlify with just a few clicks. The example site explains how.

Just show me behind the scenes right now!

If you'd want to take a look at how things behave for the moderator of a site using this system without grabbing a copy of your own, this short video will walk through a comment being made, moderated and incorporated into the site.

The post JAMstack Comments appeared first on CSS-Tricks.

Syndicate content
©2003 - Present Akamai Design & Development.