Web Platform Team Blog



Making the web awesome

CSS Regions polyfill – better, smarter, fuller

We first started work on a CSS Regions prototype to give designers and developers a seamless and flexible way to flow content inside a chain of boxes. As the feature gained visibility, it became clear that people wanted to experiment outside the WebKit-based browsers. So about one year ago, we created a rather simple polyfill supporting only basic functionality. Today, we would like to introduce a much-improved CSS Regions polyfill library, created by Francois Remy.

What’s new

What’s new? Basically everything the new polyfill was re-written from scratch to make it more flexible and feature rich. Under the hood, it is based on a general-purpose CSS parser. This means it’s more robust and less likely to produce unexpected results if your CSS is odd-looking (minified, uglyfied and so on).

The most readily apparent difference from the old polyfill is that it drops the support for the −adobe prefix and instead only supports the standard, non-prefixed form of the properties and APIs. If your stylesheets are future-proofed with the standard, non-prefixed syntax, the new polyfill is essentially a drop-in replacement: you don’t need to do anything else! :) Also, all CSS properties are supported: along with flow−from and flow−into, region−fragment, break−before and break−after are supported (Keep in mind, Safari uses the old syntax for forced breaks inside regions, −webkit−region−break−before and −webkit−region−break−after).

Another notable addition is the support for the Regions CSSOM. This covers the NamedFlow interface, additions to the Element interface corresponding to the Region interface and support for the NamedFlow events (regionoversetchange and regionfragmentchange).

Unlike the old polyfill that required the Regions-specific code to be inlined within the HTML, the new polyfill fully supports external stylesheets. It also automatically updates the layout when the DOM is changed through JavaScript or when the viewport size changes through resizing or device rotation.

Also, unlike the old polyfill, the new polyfill doesn’t require the regions to have their size explicitly set.

What’s the catch?

This is a polyfill. It’s not the real deal and has some gotchas you should be aware of.

First of all, interactive content like form elements, contentEditable elements or user-interaction pseudo-classes (for example, :active, :hover) and JavaScript event listeners are something of a shot in the dark. The polyfill actually clones the contents of the named flow to move them through regions. This will likely cause interactive content to work in unexpected ways. Another effect of the content cloning is with the CSS cascade. The new DOM structure could make some selectors not apply anymore or new selectors to apply where they wouldn’t before.

This polyfill is doing the layout asynchronously. So, the user may experience content flickering, especially if scrolling before the page layout is complete. Especially with more complex layouts, auto-sizing can behave differently than a browser-native implementation.

Another missing piece is support for region styling – neither the standard ::region() pseudo-functional syntax nor the old and no longer standard @region syntax.

In terms of CSSOM, the NamedFlow.getRegionFlowRanges() is not implemented. Furthermore, the timing of the NamedFlow events is not guaranteed to be the same as a native, standards-compliant implementation. This means some events could be fired more often or with a delay when compared to a native, standard-compliant implementation.

Demo time

If you want to see the new polyfill in action you can check out the Regions samples hosted on CodePen. Where possible, we’ve converted the samples to render with the polyfill if the browser doesn’t support CSS Regions natively. Also, two important demos showing some of the major use cases of CSS Regions – the National Geographic Orphan Elephants demo and the Adaptive UI demo – are now polyfill-enabled so you can enjoy them on any browser, not just Safari.

How to get it

You can grab a copy from Francois Remy’s GitHub repository. There you will also find extensive documentation of what the polyfill does and how it does it.

Feel free to grab a copy, give it a run and, if something bugs you, don’t hesitate to file an issue or send out a pull request.

Designers Who Code Meetup in SF

Are you a designer who also codes? We’ve got just the meetup for you!  The Designers Who Code meetup group will be hosted at Adobe’s SF office on Wed, March 5 at 6pm. Join us for an evening of good talks, networking, drinks and fun. The line-up of speakers includes Divya Manian and CJ Gammon:

There will also be tables set up for folks to mingle and meet with the teams behind Edge Tools + Services. Plus, we’ll be holding a raffle for Adobe Creative Cloud memberships.

Event Schedule
6:00 – 7:00: Food, Drinks, Networking & Product Exploration
7:00 – 8:15: Talks
8:15 – 8:30: Speaker Q&A
8:30 – 9:00: Networking

Web + Wow: An Exploration of the Web as a Medium
with CJ Gammon

The web is becoming an increasingly mixed medium with the growing list of technologies we have at our disposal. In this session we will discuss rich web experiences and different techniques used to achieve them. We will also cover new and upcoming web features and explore how these may change the way we create rich web content in the future.

Unmasking the GPU: Using Hardware Acceleration Correctly in CSS
with Divya Manian

Browsers have been offloading more and more of newer CSS features to be processed by the GPU. This is a new unmapped territory which makes it more important to understand how and when browsers do this, so you can prevent disruptive behaviour for your users that may even end up in crashing their computers. Learn which CSS properties are accelerated, how and what you can do to make sure you know when and how to use them correctly to ensure smooth experience.

Lightning Talks
Have something interesting you’d like to talk about that you can present in five minutes or less? Reach out to us with a title of your topic and a brief description on what it encompasses to see if it’d be a good fit for this event.

For more information and to RSVP, go to the Designers Who Code Meetup page.

Improving your site’s visual details: CSS3 text-align-last

In this post, I want to give a status report regarding the text-align-last CSS3 property. If you are interested in taking control of the small visual details of your site with CSS, I encourage you to keep reading.

The problem

First, let’s talk about why we need this property. You’ve probably already seen many text blocks on pages that don’t quite seem visually correct, because the last line isn’t justified with the previous lines. Check out the example paragraph below:

Example of the CSS3 text-align-last property

In the first column, the last line isn’t justified. This is the expected behavior, when you apply the ‘text-align: justify’ CSS property on a container. On the other hand, in the second column, the content is entirely justified, including the last line.

The solution

This magic is the ‘text-align-last’ CSS3 property, which is set to justify on the second container. The text-align-last property is part of the CSS Text Module Level 3 specification, which is currently a working draft. The text-align-last property describes how the last line of a block or a line right before a forced line break is aligned when ‘text-align’ is ‘justify’, which means you gain full control over the alignment of the last line of a block. The property allows several more options, which you can read about on WebPlatform.org docs, or the CSS Text Module Level 3 W3C Specification.

A possible use case (Added April – 2014)

After looking at the previous example (which was rather focusing on the functionality of the property), let’s move on to a more realistic use case. The feature is perfect to make our multi-line captions look better. Check out the centered, and the justified image caption examples below.


And now, compare them with a justified, multi-line caption, where the last line has been centered by text-align-last: center.

I think the proper alignment of the last line gives a better overlook to the caption.

Browser Support

I recently added rendering support for the property in WebKit (Safari) based on the latest specification. Dongwoo Joshua Im from Samsung added rendering support in Blink (Chrome). If you like to try it out in WebKit, you’ll need to make a custom developer build and use the CSS3 text support build flag (--css3-text).

The property is already included in Blink’s developer nightlies by default, so after launching your latest Chrome Canary, you only need to enable ‘Enable experimental Web Platform features’ under chrome://flags, and enjoy the full control over your last lines.

Developer note

Please keep in mind that both the W3C specification and the implementations are under experimental status. I’ll keep blogging about the feature and let you know if anything changes, including when the feature ships for production use!

Using blend modes in HTML Canvas


Canvas blending is an HTML feature for designers and web developers. In this blog post, I  present the syntax and some use cases where blend modes are particularly useful.

What are blend modes?

To put it simply, blend modes are ways of combining two graphic objects using special mathematical formulas.

Recently, blend modes have landed in HTML 2D Canvas. The feature is enabled in Apple Safari, Mozilla Firefox and Google Chrome.

At a first glance, blend modes seem to be no different than transparency, but in reality, the results achieved with blending are much more expressive than using simple opacity. In practice, blending is generally used together with transparency.

If you want to read more about each of the blending operations, you can check out How To: An Explanation of Illustrator’s Blending Modes by Sara Froehlich.

Using canvas blending

To use blend modes in canvas,  set the globalCompositeOperator property of the Context 2D Canvas, as follows:

 Javascript |  copy code |? 
// Get the canvas element. "cvs" is the id of the html canvas element.
var canvas = document.getElementById("cvs");
// Get the Context object.
var context = canvas.getContext("2d");
// Set the blending operation.
context.globalCompositeOperation = "multiply";

After this block is executed, any graphic elements drawn on the canvas are blended using the “multiply” blend mode.

In the first example, there are two assets: a raindrop pattern and a picture of a building. We’d like to make the building look as if it’s reflected in the raindrop.

Check out this Pen!

To achieve this result, we first draw the raindrop picture. Once this operation is finished, we set the blendMode of the canvas to soft-light.

In the next step, we draw the second image. Click the button to preview the effect. As you can see, the result looks like a reflected building.

Finally, we add one more effect: we blend the result with a linear gradient. All we have to do is create and draw the gradient in the canvas, since the blending operation is already set. You can see the result by clicking on the button.

After finishing these tasks, we want to prevent any further elements drawn into the canvas from blending.

This means we have to clear the blending operator, as follows:

 Javascript |  copy code |? 
context.globalCompositeOperation = "source-over";

The next demo showcases two of the most extensively used blend modes: screen and multiply.

Imagine the following scenario: you are developing a game where a character is trapped in a dungeon. The dungeon consists of a dark cavern. The player needs a light source. Let’s see how we can achieve these results with blending:

The following pen shows this result. Use the W, A, S, D keys to travel around the map. Press any other key to intensify the light source.

Check out this Pen!

Here, we use the multiply blend mode to darken the map: this is done by drawing the actual map as an image, followed by setting the blend mode of the canvas context to multiply. Next, a gray rectangle is drawn on top of the initial image. The darkening effect is now complete.

The second use of blending is to simulate the light emitted from the character in the dungeon. For this, we use a radial gradient, from transparent to yellow. This gradient is now blended with the backdrop using the “screen” blend mode operation, thus simulating the effect of a torch.

The next example shows how fog effects can be simulated using blend modes. If you hover over the next pen, you will see how fog is dynamically added to the canvas. How is this achieved?

Check out this Pen!

Radial gradients from transparent to white are added to the photo, using the soft-light blend mode.

In general, when using blend modes, the result can sometimes be too intense. In order to temper this, it’s a common pattern to blend with transparency. The trick is to tune the blending result by setting opacity on the layer that is blended. As shown in this example, varying the opacity of the gradient’s color actually determines the density of the fog. You can set the fog density through the slider at the bottom of the page and observe how the result if more powerful for higher opacity.

Here’s another effect that can be obtained with canvas blend modes: let’s say you are designing a game where the player controls a character. If the character has low hit points, you can flash the player’s screen, with red, as a warning sign. In the next example, this is done by drawing a red rectangle on top of the whole canvas, using the overlay blend mode.

Check out this Pen!

This shows the power of blend modes. You can click the radio buttons to switch the way the overlay rectangle is drawn. The blending result is clearly better than the one using only transparency.

My last example is a solution to the following problem: you have a pattern and you want to draw a group of elements, and blend this whole group with the pattern. If you set the blend mode of the canvas and start drawing the elements of the group one by one, they blend with each other, causing an undesirable result.

Check out this Pen!

Thankfully, as shown in the following pen, there is a solution for this problem: In this example, we have a t-shirt pattern and a robot. The robot is made of a group of elements.

To blend the robot with the t-shirt pattern, this is what you have to do:

Draw the robot in a new canvas. This is achieved by creating a new canvas element. When we’re done drawing the robot, we set the blend mode on our original canvas and draw the newly created canvas on the original one, as follows:

 Javascript |  copy code |? 
// This creates a new canvas where we’ll draw the robot.
var layerCanvas = document.createElement("canvas");
var layerContext = layerCanvas.getContext("2d");
// Actually draw the robot.
layerContext.fillStyle = "purple";
layerContext.arc(50, 50, 40, 0, 2 * Math.PI);
layerContext.fillStyle = "navy";
layerContext.fillRect(5, 35, 90, 30);
layerContext.fillStyle = "purple";
layerContext.fillRect(20, 40, 20, 20);
layerContext.fillRect(60, 40, 20, 20);
// Set the blend mode of the original canvas
context.globalCompositeOperation = "overlay";
// Blend the robot with the pattern.
// Drawing the newly created canvas on top of the original one.
context.drawImage(layerCanvas, 100, 70);


In this blog post, we show the usage of canvas blend modes and provided some examples, most of which can be used in designing games or photo editing. Finally, we highlight the differences that opacity makes when used with blending, and why blending is different than simple transparency.

We’d love to hear from you, either if you have questions, demos or thoughts on this feature.


Here are the code samples used in this blog post:

  1. Example 1: Reflected building.
  2. Example 2: Light effect.
  3. Example 3: Fog effect.
  4. Example 4: Flashing screen.
  5. Example 5: Blending groups. T-shirt design.

Adobe SXSW 2014 Creative Camp

Adobe is traveling to SXSW for our Annual Creative Camp, Friday March 7th at the Radisson Town Lake, Riverside Ballroom. This year we have five sessions on topics shaping the modern web. Relax in the Typekit pop-up library, a hang-out with 65+ specially-curated design books. Plus, you’ll need your fuel to make it through SXSW and we’ve got you covered all day with lunch, and snacks galore – flavored popcorn, mini-burgers and petit BLT’s plus a happy hour during our final session of the day.

Here’s our session line up:
What Do We Build Next? 11:00 – 12:00
Get behind the scenes at Adobe and learn how our product development teams go from just an idea to a functional prototype ready for testing with real users in a matter of weeks for their newest web authoring tools. Devin Fernandez, Principal Product Manager, and Winsha Chen, Senior Computer Scientist will show examples of real projects under development right now.
5 Things Developers Need to Know About Design 12:30 – 1:30
In this session you will learn with Adobe Evangelist Paul Trani the techniques designers use as well as the things they wish every developer knew about design. Understanding these 5 things will not only make you better at design, it will help you work better with designers. We’ll also be serving lunch during this session so make sure you come early to grab a sandwich and get a seat.
Rich Web Experiences & the Future of the Web 2:00 – 3:00
We’re reaching a point where ideas we could only dream of in the past from interactive film to global multiplayer 3D gaming can become a reality, all living inside of your browser. We’ll explore inspiring examples of how the web can be used to create rich media experiences and what’s possible in the future with Adobe Creative Technologist CJ Gammon.
The Onions of Interactive Infographic Design 3:30 – 4:30
Interactive infographics make it possible for you to truly capture your audience and engage with them in a manner that simply is not possible when merely citing dry facts or statistics. This session will cover the value of creating animated, interactive infographics with HTML your readers care about using Adobe Edge Animate with Product Manager, Sarah Hunt.
The Ultimate Developer’s Tool: Theory & Discussion 5:00 – 6:00
What do iOS, Android, and the Internet all have in common? They were all built using source code editors driven. But what qualities are needed in a modern code editor? Enjoy some cold beer and snacks while you engaging in a discussion with Senior Product Manager, Jonathan Dunlap, on how we can use our present knowledge to build the ultimate source code editor.

These sessions are official SXSW events. A badge is required to attend and no registration needed.

Using HTML for Rich Media Advertising

As web technologies like SVG, WebGL, and Canvas continue to get richer, more expressive, and better supported, it makes sense to start turning to them more frequently for common rich media solutions like advertising. That’s why, when the Adobe Web Platform team got the opportunity to sponsor CodePen for February, we decided to make a self-referential ad that uses SVG technology to promote SVG technology. Here’s what we came up with:

Specifically, the ad promotes a project called Snap.svg, a relatively new open-source SVG JavaScript library (think of it as a super lightweight version of jQuery, but for creating, animating, manipulating, and querying SVG content). And, of course, all the animations in the ad are done with Snap.

While creating the ad, we were happy to find that the designer/developer workflow was really smooth since we were able to maintain a vector workflow throughout. Designing the storyboard and artwork in Illustrator not only allowed us to maintain a clear vision of what the end result would be, but it also allowed us to generate vectors that could be used directly by Snap. The final step was to integrate Snap for animating and manipulating the SVG, resulting in the final creative.

Another big advantage of SVG is that we essentially got responsiveness for free. The ad can be served in any size iframe and it will automatically scale and look perfect. That gives the publisher (in this case, CodePen) maximum freedom when it comes to displaying the ad, and it means that the creative looks (and works) great in both desktop and mobile browsers.

If you’re doing rich media work on the web, I highly recommend that you go check out Snap.svg. And if you want to learn more about how the ad was put together, feel free to check out the source code.

Observations from the CSS Working Group Meeting


Two weeks ago I had the opportunity to attend the CSS Working Group meeting in Seattle. I am not an official member of the Working Group and so couldn’t participate in the discussions. I was able to observe and see how the next generation web technologies are made.

The meeting lasted three full days and was held at the Adobe Seattle office. The weather was rainy and overcast. The setting was beautiful. And the discussions proved to be the best attraction of all. Many of the members have been working together for over a decade. It is clear they have developed some strong bonds and mutual admiration for one another’s technical opinions and expertise.

On the first day of the meeting, a schedule is set by allocating a time slot to each topic, the duration of which is estimated on a case-by-case basis. As topics come up, one person often takes the lead in explaining the context and the proposal at hand, and others chime in with opinions and questions. In most cases, consensus is reached without much difficulty. On some topics however, strong disagreements may exist, and ultimately, a vote is required in order to gauge the group’s consensus. This happened a couple times, but in all cases an overwhelming majority of attendees supported a specific proposal, with just a couple of people dissenting or abstaining from the vote altogether.

A significant amount of progress was made at the meeting on a wide range of specifications. To name just a few:

  • There was a good discussion around media queries
  • Some bugs were resolved
  • A decision was made to add mathematical operators to the syntax (i.e., width < 700px), even though it would have to be escaped in XML
  • There was a lively discussion that resulted in a decision to expose shape reference boxes in SVG
  • An agreement was reached to poll web authors as to whether to use ! or :has() in CSS

Much more was covered as well, all captured in the publicly available CSSWG Minutes Seattle F2F.

It was truly fascinating to witness the technical debates and hear different members stake out their philosophical and technical positions on specific topics. The discourse always remained civil. While at times it seemed as though topics veered off track, in the end, issues were resolved one way or another.

The biggest takeaway for me was the dedication the working group members have in finding the best technical solution for the web. This one meeting was just the smallest of drops in the huge bucket of effort that the group as a whole, and each member individually, has devoted to moving CSS specifications forward. It was very encouraging to see that all of the attendees genuinely cared about the future of the web as a platform, and displayed an admirable level of effort and patience in order to make it a reality. I came away feeling confident that the right balance was being struck on the next set of feature specifications and that CSS was in good hands.

New CSS Shapes Syntax

The CSS Shapes specification has moved to Last Call. This move has brought a whole host of syntax changes, and we have updated the Blink and WebKit implementations accordingly. Read on for a summary of what has changed in the specification.

Note on the examples

If you wish to view the examples live on CodePen when reading this article, you need to get a browser that supports CSS Shapes and make sure they are enabled. If that sounds interesting, take a look at our browser support page, which will tell you which browsers support Shapes and how to enable it.

Box values

You can now define shapes based on the CSS Box Model of the element the shape applies to. The shape can be declared as the margin-box, border-box, padding-box, or content-box. This shape conforms to any border-radius that has been specified on the element. And if you would like to take a look at CodePen, there is an example of the box values being used as shapes.

box values example

Basic Shapes with box values

You can also specify a box value along with a basic shape. This box value is referred to as the reference box for the shape. This causes the basic shape to use that box instead of the default box to determine things like sizing and position of the shape. The default box depends on which property you are setting the value for: shape-outside defaults to margin-box, while clip-path defaults to border-box. For example, the following two properties could define entirely different circles depending on the margin, padding, or border that is applied to the element:

shape-outside: circle();

shape-outside: circle() content-box;

If you don’t understand the use of circle() here, don’t worry. The next section covers all of the shapes and the changes that apply to them.

Basic Shapes

Basic shapes are at the core of the CSS Shapes module. Most of the shapes have been changed from a SVG-style syntax to one more in line with other CSS properties. With the exception of polygon, all other shapes have undergone significant alterations.

rectangle and inset-rectangle are now inset

A single shape, inset, has replaced the rectangle and inset-rectangle shapes. This shape defines a rectangle with sides that are inset from the sides of the reference box by a given amount.

Basic inset syntax

The basic syntax for inset is like that of the margin shorthand. If you supply one argument, then that argument specifies the inset for all four sides of the rectangle:


If you specify two arguments, the first argument specifies the inset for the top and bottom, while the second argument specifies the inset for the right and left:

inset(top_bottom right_left)

You can also specify three arguments, where the first argument specifies the inset for the top, the second argument specifies the inset for the right and left, and the third argument specifies the inset for the bottom:

inset(top right_left bottom)

Finally, you can specify four arguments, in which case, each argument specifies the inset for a different side, like so:

inset(top right bottom left)

There are some live examples of inset with different arguments on CodePen.

inset examples

Rounding the corners

It doesn’t stop there! You can take any of the forms above and add the round keyword and then use the familiar border-radius syntax to define rounded corners for the resultant rectangle. A very simple example:

inset(30% round 10%)

Of course you can do more complex things:

inset(10% round 10% 40% 10% 40%)

You can see the following more complex inset shape examples live on CodePen.

inset with rounded corners example

circle and ellipse - same names, different arguments

Both circle and ellipse are still with us. However, the arguments they take have changed significantly.

How to specify radii

To start, radii are no longer exclusively lengths or percentages. There are two new keywords that can be used to define the radii: closest-side and farthest-side. Both of these keywords refer to the distance from the center of the shape to a side of the reference box.


closest-side uses the distance from the center of the shape to the side of the reference box that is closest to the center coordinate of the shape. In the case of a circle, this is as simple as measuring the distance between the center of the circle and each side of the reference box and using the minimum distance. It is a little more complex in the case of an ellipse, since the ellipse has two radii: one in the horizontal direction (rx), and one in the vertical direction (ry). To compute the closest-side value for an ellipse, only the sides in the direction of the radius in question are considered. For example, to find the closest side for ry, you would only compare the distances between the center and the two sides in the vertical direction.

For example, circle() is the same as circle(closest-side), which defines the largest circle that will fit within the reference box. And ellipse() is equivalent to ellipse(closest-side closest-side), defining the largest ellipse that will fit within the referemce box. You can see the following example of circles and ellipses defined with closest-side live on CodePen.

circle and ellipse example


farthest-side is analogous to closest-side, it just looks for the distance to the side of the reference box that has the largest distance from the shape’s center. Just like with all of the previous examples, you can see the following circle defined with farthest-side on CodePen.

circle farthest-side example

How to define the center

It isn’t just radii that have changed. You now can use the full CSS position syntax to define the center of the shape. This is done by including the at keyword and following that with a position, like so:

circle(closest-side at center)

And yes, this example of a positioned circle is available on CodePen.

positioned circle example
If you read the previous section, you might realize that the result looks exactly the same as the example for circle(). That is because this is the full expansion of that shorthand. Note that circle(at center) is yet another way to say the same thing. All of the arguments are optional, and they all have defaults.

You can of course position an ellipse or circle at a different point than the center. It is beyond the scope of this article to cover all of the options here, but I can give a few examples.

ellipse(at top 50% left 20%)

circle(25% at 25% 50%)

If you would like to play with this or see it in action, you can check out the positioned ellipse and circle example on CodePen.

positioned circle and ellipse example

How do I use these shapes?

The CSS Shapes specification defines a shape-outside directive that changes the wrapping behavior of floats so that content can wrap around an arbitrary shape. All of the examples in the previous sections use shape-outside. In addition, these shapes can be used with the clip-path property, from the CSS masking specification. If you look closely at all of the examples used in this article, they all use the clip-path property to visualize the shape.

Further reading

This article has just covered some of the largest changes that have come with the move to Last Call. Future blog posts will cover use of these shapes and the other shapes types defined in CSS Shapes in more detail. If you can’t wait, you can always take a look at the CSS Shapes specification for the authoritative take.

Baseline Grids for the Web

Visual design often has a vertical rhythm, laying out text and graphics at regular vertical intervals. This makes side-by-side content line up nicely. In printing this allows lines of text occupy the same vertical position on either side of the page, to prevent your eye from noticing any ink showing through thin paper.

A vertical rhythm is accomplished by using a baseline grid, either implicitly or explicitly. In traditional publishing, you can implicitly use a baseline grid by using consistent leading and fiddling with any exceptions that arise. Or there are tools that help you set up an explicit baseline grid. On the web, fiddling with exceptions isn’t something you can (or should) do. So the implicit option just doesn’t work. And the web has so far lacked an explicit baseline grid.

Here’s an example of why you might want to use a baseline grid. This site has three side-by-side article summaries. Headings and body text have slightly different line heights, and different screen sizes will produce different numbers of lines for the headings. So the body text from each summary does not line up with the others.


It’s a bit easier to see what I mean if I add some lines to the picture. If all of the body text aligned its baselines to the green lines, the side-by-side content would share a vertical rhythm and look less sloppy.


You can (usually) achieve a consistent vertical rhythm today by forcing all line heights to be strict multiples of the body line height. The site I pulled this example from actually does try this. The heading and body text in their summaries use exactly the same line height. So the headlines are a little too tightly spaced and the body text is a bit too loose. And unfortunately, other elements on the page mess with this consistency, so the body text doesn’t line up anyway.


It’s generally better to specify slightly larger line height for larger text, but then you can’t have everything line up to the baseline grid, or you get something like the result above. So in order to use an explicit baseline grid, you need to be able to say that some parts of the design snap to the grid, and other parts ignore the grid. If you only align the body text, you get this result, which is a bit better than the original.


Then you can start playing with having blocks align to the grid as well as text lines. Each heading can be considered as a block of lines that can interact with the grid as a unit. Perhaps you’d like the first baseline of each heading to align with the grid:


Or you could have each heading center all of its content in-between two grid lines:


The differences between the last two are subtle, but aligning the first baseline gives you better side-by-side consistency in the headings, and centering gives you more consistent spacing between the headings and the body text. Which to choose depends on the design you’re trying to express.

I believe that CSS needs an explicit baseline grid feature, and am now working with the CSS Working Group to figure out the best way to define and use a baseline grid in web design.

Improving text selection in CSS Regions – take 2

It’s been three months already since our last update on the work our partners at Igalia contributed to improve text selection for pages that use CSS Regions. In the meanwhile, a good amount of progress has been made, both in terms of clarifying the expected behavior and actual implementation work in WebKit and Blink.

If you’re in a hurry, here’s why this matters: Currently, the way text selection on the web is specified, lacks the flexibility needed to make it behave intuitively in modern web design. Not only that, but CSS features (like Flexbox or Regions) that break the direct mapping between elements in the document and the actual content rendered on the screen may yield highly unexpected results for the end-user. Thus, discussing the possible standardization solutions and implementing them is important for creating a more usable web.

You can head over to Javier’s and Rego’s blog posts for all the nitty-gritty details (and a smooth video :) ) of the fixes needed in WebKit. Hopefully they will make their way into the WebKit trunk, providing pages that use CSS Regions better and more intuitive text selection behavior.