Experimenting with CSS Exclusions

Okay, this is going to be scattered and on the cutting edge side, so buckle in. Adobe has been hard at work making the web a little bit richer when it comes to how type is displayed. A great example of that is CSS Regions, which let you create linked islands that text can flow between so you have a lot of control over how text gets laid out on the screen. That’s currently in the “Canary” builds of Chrome and if you go to about://flags and turn on “CSS Regions” you’ll be able to view the demos. The other thing we’ve been working on is a bit further out, but it’s in the same vein. It’s called CSS exclusions. It essentially lets you create more interesting islands of text in the form of shapes that text will flow around. At this stage it’s still very, very early. In fact, the only way to test CSS exclusions content is with a special build of WebKit that’s available on Adobe Labs.

The Backstory

A lot of the demos associated with these features are associated with magazines, and especially with the iPad 3 coming out, it’s going to be critical to be able to build expressive content that scales. Since magazines are mostly text, expressive text will be a big deal. I’ve been mulling over doing a beer-related magazine and figured it would be cool to try out some of the CSS demos to create something that might look unique and fit in a beer magazine. So I thought “hey, I could create shapes of different beer glasses and run text through those!” That was the basic premise. As I dug in, I found a couple of caveats. Most I’ll get to throughout the post, but the biggest one is that there currently isn’t a version of WebKit that has both CSS Exclusions and support for flowing across CSS Regions. So my original idea ran into a small roadblock but I’ll be able to fix that down the road.

Creating regions

The CSS Exclusions spec supports SVG’s basic shapes. That includes circles, rectangles, and polygons. At this point it can’t do arbitrary path data but you will be able to use SVG data according to the spec. So I started with creating the various types of beer glasses in Illustrator with the polygon tool. Then I had to set up the glasses on the page and make text flow correctly. The standard method seems to be to create two CSS classes, one for the properties that every region or shape will have, and another class for the specific region, in this case, glass type. I called my main region container and it looks like this:

     .container{
          position:absolute;
          height:500px;
          width:300px;
          text-align:justify;
          margin-top:0px;
          font-size:10px;
 
          -webkit-wrap-shape-mode: content;
          -webkit-render-wrap-shape: none;
          -webkit-hyphens:auto;
     }

The main properties are those three on the bottom. The first one tells the browser what I’m doing, and that’s wrapping the content within a shape. I think the other option here is around, which would make the shape an exclusion but I don’t think that’s working in my build of WebKit (or I’m doing it wrong). The render-wrap-shape is good for debugging as it shows you an outline of the shape so you can see how it’s appearing. I found this incredibly helpful as I laid objects out on the page. The last one, hyphens, lets you tell the browser how you want it to break up text. If you go for none there, it will only flow full words within the content. Otherwise it fills the content as much as it can before breaking words with a hyphen. For fuller-looking shapes, go with hyphens set to auto.

Next I had to set up the specific glass shapes. The hardest part for me was lining things up correctly. The way I created the polygons I think made it tougher to lay out. It also doesn’t change as you resize the page because I’m not using percentages (if that’s even possible with polygon objects). It looks kind of ugly but to define a shape we just have to use webkit-wrap-shape and give it the values. Here are a couple I did.

     #irishpint1 {
          padding-left:0px;
     }
 
    .irishpint {
          -webkit-wrap-shape: polygon(157px,473px 106px,472px 93px,453px 91px,432px 87px,401px 84px,368px 78px,332px 70px,294px 61px,255px 57px,225px 55px,191px 55px,165px 57px,128px 63px,118px 165px,118px 274px,120px 279px,128px 282px,164px 282px,190px 282px,226px 274px,263px 267px,296px 257px,337px 253px,368px 250px,397px 246px,427px 244px,453px 233px,473px 173px,473px);
     }
 
 
     #weissbierflute1 {
          padding-left:250px;    
     }
 
     .weissbierflute {
          -webkit-wrap-shape:  polygon(104px,470px 82px,459px 81px,439px 89px,400px 105px,344px 102px,294px 86px,238px 72px,183px 66px,128px 62px,77px 59px,39px 58px,17px 57px,0 280px,0 279px,17px 278px,41px 276px,74px 271px,128px 265px,182px 251px,238px 234px,299px 232px,344px 248px,400px 255px,434px 252px,463px 215px,473px);
     }

So they’re some semi-complex polygons. I also used the div tags to set up padding and lay things out. One of the things I learned is that CSS regions/shapes can only be applied through classes, you can’t define the properties based on id’s. But that may change.

So with all of those glass polygons, it looks like this:

What the page looks like in a browser that supports CSS Exclusions

What the page looks like in a browser that supports CSS Exclusions

That page is up on GitHub but you won’t be able to view it in your browser so you’ll have to be looking at it with the special browser from Adobe labs.

Making it More Interesting

After this I thought it would be cool to do a bit more with the shapes. Beer has a rating scale for color called the SRM scale. Types of beer have a general range of SRM scales and since some glasses roughly correspond to specific types of beers I wanted to see about creating a background for each shape that would correspond to the SRM scale. But even more than that I wanted it to change with the glass so as the glass got narrower, the background would become more transparent just like a real beer glass. Unfortunately it didn’t work quite the way I wanted, but I learned a bit about using CSS shapes along the way. Originally I just started by giving the div a background:

     #irishpint1 {
          padding-left:0px;
          background: -webkit-gradient(linear, left top, left bottom,
                                             color-stop(.8, rgba(152,83,54,1)),
                                             color-stop(.2, rgba(152,83,54,.7)));
     }

But the CSS shapes/exclusions don’t actually change the shape of the div, they’re only worried about wrapping the text within the div. So my page just looked like this:

What the div tag looked like when trying to set the background

What the div tag looked like when trying to set the background

Luckily webkit-mask-image came to the rescue. With that, I could create a mask based on a file, in my case an SVG file, and use that to mask a block element like a div tag. So I went through and created an SVG file for every glass shape and then used those as the mask and set the background accordingly with rbga() properties in a gradient. The final version looks like this:

And here’s a clean(ish) version without the backgrounds. I kind of like this one better.

Update: If you have a browser that supports exclusions you can check out the demo here.

Final Thoughts

It’s really, really early for CSS Exclusions but there is a LOT of potential there and even the stuff that works now is a lot of fun to use. This was just an initial dive into the feature to kick the tires, and because it’s so new, there are a lot of gaps both in my knowledge and what I was able to do. One of the things I tried was using CSS3 transitions to animate the -webkit-wrap-shape property. That didn’t seem to work, it could be on the roadmap.

It’s a fun feature and it’s really fun to be able to give it a shot while it’s still in the early stages. For magazines or any kind of rich text content, exclusions are going to be a fantastic way to make stuff pop. If you want, you can check out the project on Github. I’ll probably be modifying it and improving it as the spec evolves.