Why I run my business like an open source project

When I first started consulting, I used to squirrel away in my corner and code. Some weeks later, I’d deliver my perfect shining gem to the client after, quite frankly, trying to talk to them as little as possible throughout most of the process. It wasn’t that I didn’t like people, I especially enjoyed talking with developers, but the gap between what I knew I needed to do to get the job right and my ability to explain it to the client seemed insurmountable. With repetition, my ability to explain technical requirements in a management friendly way has evolved to something like passable, but an equally important change has been Github.

Github

Github has allowed us to take a different path with our projects. We now treat them much like open source projects. We strive for transparency and clarity in everything we deliver as well as in the process by which we deliver it. We often do complex UI rewrites and performance evaluations for big companies like Facebook, Paypal, Adobe, Salesforce, Trulia, Williams Sonoma, Pottery Barn, etc. Big companies have a lot of stakeholders and we’ve found that Github is an amazing way to include them in the project from the beginning.

Our clients have access to the code we are writing from the first line we commit. When my developers and I code review each other’s work, the client can see and also participate in that code review. In that way, they get to understand (and buy in on) not only the end result, but the rationelle behind it. Clients also send their developers to work side by side with us. We take them in as a part of our team, submit them to the same grueling code reviews we all go through.

We’ve found that they are happier this way. The transparency I feared, the risk taken by trying to explain something and failing, has been far outweighed by the practical benefits of healthy collaboration. They now feel the end result belongs to them, rather than being something forced on them from outside or upper management.

Glorious bugs…

There is also something great about letting a client peek inside the works… they find bugs, omissions, and misunderstandings. Why is that great? Because they find them right away, rather than several weeks or months into a project. They also feel empowered to open github issues for those bugs, helping us do our job even better. Instead of it being a terrible thing to find bugs, it becomes an ordinary part of the process. I usually explain it like popcorn popping. For a while you will have a lot of pops, and then slowly it will wane and you’ll just get a pop every now and then. When the pops become pretty infrequent, we move the code from our repo to theirs. I hope this means our clients trust us, because they get to see that we will continue to show up for them throughout the project and that we’ll always have a curious, relaxed, and grateful attitude when they identify something that needs fixing.

We didn’t want you to work on that!

It also means that there isn’t any issue of “we didn’t ask you to work on that”. The client gets to approve all work (in the Github issue for the feature) before we even get started. They also get to see the kind of bugs I assign to Fiona, or she assigns to Arnaud and get a sense of the teams strengths and weaknesses. That helps them know who to contact when an issue comes up. Yay for anything that makes me less of a bottleneck. :)

And the most important reason? Code quality

I’m a firm believer that open source code is of higher quality than code written in a vacuum. I can’t say if that is true for every project out there, but it has certainly been true for us. Greater transparency has enabled us to have a tighter feedback loop and make a few things I’m quite proud of.

Anyway, I could go on and on about this because I’m quite passionate about how an open source approach and Github in particular has enabled us to improve our work, but I’d love to hear from you. Have you used github in this way? Do you use it internally? What works? Any tricks? I know their are a few features I still wish existed, how about you?

CSSConf – The selection process

CSSConf – This is your conference.

Last week we invited the CSS community to submit talks for the upcoming CSSConf (May 28th, Amelia Island, FL).

The CSS community has an excellent history of curated conferences, and yet we want to do something a little bit different. We want to see what you have to say! What do you think is cool? What are you working on that you would like to share with the community? We decided to do a Call For Proposals because we wanted to balance curation with community.

Some folks may not be familiar with a CFP. It comes from the scientific community, when scientists would submit a proposal to present their work to their peers. The scientists with the most interesting abstracts would then be chosen to display a poster describing their work at a conference.

We decided to build on this model because we firmly believe that the community is doing amazing things. We are excited to hear about them, and to help you share your work with others.

Choosing the best talks

We are following the JSConf EU method so that we can choose the absolute very best proposals that come in.

The most important part is that we have eliminated all identifying details when we are evaluating the quality of your proposals. We won’t see your name, your company, or whether you have spoken before or are brand new to speaking. This means you have a chance to speak if you are famous but also if you have never set foot on a stage. Each of the proposals will be evaluated on it’s own merit. We’re excited about this process, and we hope you are too.

(After the first two rounds of selection are complete, we will reveal your names/locations so that we can do important things like figure out if travel from your location will fit in our budget).

Submit your proposal

If you want to know a little more about how we’re doing it, or, even better, you want to submit a proposal, head on over to the CSSConf Call for Presentations. Thanks for being a part of this. If you have any questions, or need any help getting your proposal together, don’t hesitate to get in touch with us at contact@cssconf.com.

Cross-Browser Debugging CSS

I was helping Laura (a developer who works with me) learn about cross-browser debugging this week, which got me excited to share my process.

The first principal is simply:

Work with CSS, not against it.

CSS has an underlying design and when you work with it, with the natural flow of how CSS is meant to be used, you will find you have a lot less bugs. I learned CSS by reading the W3C specifications, which is why I began coding according to the language’s design, but however you learned it, you can pick up some of the key points involved.

The first thing I do is code to a good browser from the start. Our choice is Google Chrome, mainly because of the superior developer tools. When I have something working in Chrome and I am satisfied with it, I take a look at it in either Safari or Firefox.

If there is a discrepancy between these good browsers, chances are you are working against CSS. Do not try to hack around discrepancies between good browsers. Your goal is to figure out *why* it is being interpreted differently. Usually there is a very good reason. These are some of the things I check on if I have bugs:

  • HTML interpretation – did you forget to close a tag? Did you wrap an inline element around a block level element? Anything that veers off the standard will be interpreted differently by different browsers.
  • Run your CSS through CSS lint. It will give you a good sense of any errors (missing semi colon?) that might be throwing you off. For debugging cross browser differences, the errors are more interesting than the warnings.
  • Forgot to use a reset/normalize stylesheet and are relying on (different) browser default styles.
  • Browser support differences. Are you using advanced CSS3 properties or HTML5 elements? Check browser support to be sure all your target browsers are covered (quirksmode is where I usually do this). If not, you may still be able to use the fancy-pants properties, you’ll just need to design clever fall-backs for the clunkier browsers. For example, borders instead of drop shadows or square instead of rounded.
  • Margins are not being trapped correctly. If you have weird spaces in unexpected places, chances are your margins are collapsing in an undesirable way.
  • You created a new formatting context in one browser, but not in another. Typically this happens as a result of overzealous use of the zoom:1 property to trigger hasLayout in IE. Yes, hasLayout is essentially the same thing as a new formatting context in better browsers.
  • Using absolute position, without setting horizontal and vertical offset. For that reason, the absolutely positioned element will have the same position it would have had when set statically. However, if you try to manipulate the top, right, bottom, or left values, the element will all of the sudden be positioned relative to the nearest relatively positioned ancestor causing it to jump.
  • Did you combine display types in unexpected ways? For example, the spec doesn’t lay out what happens when a table-cell is next to a floated element without a table row or table in between. It doesn’t mean you can’t do it, but it does mean that if you do, you open yourself up to potential bugs and will need to spend more time cross browser testing.
  • Is whitespace affecting your layout? You almost never want to have whitespace dependencies on your CSS display, but sometimes it happens, particularly with display inline and inline block and with images since they look like blocks, but, unless you set them all to display block, don’t behave that way.
  • Rounding errors can cause display differences. All flexible layouts and grids have to deal with sub-pixel rounding errors, they each find different ways to minimize the visibility of these differences.

If you don’t read anything else, read the next two paragraphs

The most important thing to keep in mind is that error behavior is not defined in the spec. If you go off-roading you don’t know what you will get. Chances are it will be different between browsers. If you are combining odd properties (like margins on an inline element), you will have cross browser differences.

Display

I think of CSS like a choose your own adventure. When you have made certain choices, others become obvious. For example, you need to first choose your display type block, inline, inline-block, table. When you have chosen that, you are left with a tool-box of appropriate tools to use to alter the display. For example,

  • Block level elements should be used with margins, paddings, height and width. Line-height isn’t appropriate.
  • Inline elements have line-height, vertical align, and can also be whitespace sensitive. Margins, paddings, heights, and widths aren’t appropriate.
  • Tables have vertical and horizontal alignment and can sometimes behave bizarrely if you have one element of a table without the others (e.g. a table-row with no table-cell). Margins are inappropriate for table-rows and table-cells. Padding is inappropriate for tables and table rows.

If you stick to the tool box that naturally goes with your display type, you will have far fewer bugs and cross-browser differences.

Positioning

Next, if you chose block, you must choose your positioning mechanism. (The others are generally positioned according to the normal flow). So for blocks you can choose:

  • Float – brings blocks all the way to the right or left. If you floated something, you made it a block level element, which means previously applied vertical-align or line-height properties may no longer work.
  • Absolute – positions the element relative to it’s nearest position relative ancestor. Keep in mind that absolutely positioned elements do not trigger reflows and are not reflowed when ancestors and siblings are changed. This is a strength for animations, but can cause display issues if you use too much position absolute with dynamically updating content. (e.g. the old-school example is corners that do not move when more content is added to the box).
  • Static – the default, this is how you get back to a standard element in the normal flow.
  • Fixed – positions the block relative to the viewport. Rarely used.
  • Relative – mostly doesn’t affect the node it is applied to, but children will get their absolute position relative to this node.

I’m not organized enough to enumerate all the display and positioning types and tell you which can be used/not used with which other properties, so you are going to have to think it through for yourself when debugging and writing code. There are two important things to consider:

  1. Do these properties go with the display and positioning types I have chosen?
  2. Do sibling positioning types go together?

For example, does it make sense to have a float, table-cell, and inline element interacting with each other? What should the browser do with that? Is it defined in the spec? If not, you are probably going against the grain of CSS. That can be ok sometimes, but you should know exactly why you chose to do it and leave extra time for cross browser testing.

Internet Explorer

When you have resolved all the discrepancies between the good browsers, you are ready to look at IE. I recommend starting with the oldest version of IE that you need to support because lots of bugs continue to exist in newer versions (in slightly modified form) so you will have less to fix if you start with the worst one.

Even with IE, you want to try to figure out why it is interpreting something differently rather than just hack around it. Adding * and _ hacks to your code willy-nilly is like finding out a function is returning the wrong value (say four less than it should be) and just adding the difference to it rather than figuring out where the math went wrong in the first place.

return result+4;

That said, it is ok and sometimes necessary to hack IE6 & 7. IE8 usually only needs hacks to accomodate a lack of support for modern CSS3. If you think you need to hack, try to figure out the exact bug you are dealing with. There are tons of resources for this online (anyone remember PIE?). The particular problems which require hacks in IE6 & 7 are:

  • Needing to add hasLayout with zoom:1
  • Position relative causing things to disappear
  • 3px float bug
  • Expanding container float bug (useful!) and overflow hidden which unfortunately “fixes” this useful bug.
  • Do you have a favorite IE bug? I’d love to hear about it in the comments.

There are, of course others, but these are the few I’ve had to hack around for OOCSS. The others occur far less frequently, like the duplicated content bug when you have two floated elements with a comment in between. I don’t know how to explain figuring out IE bugs because, for the most part, I’ve internalized them. Like speaking a foreign language. The best I can suggest is to carefully examine what you can see and carefully craft your google search to describe it. Don’t start hacking until you identify the bug. The dev tools for IE are horrible, so you may need to use background colors to “see” the problems. I create debug stylesheets for that purpose.

Implementing solutions

When you have figured out what is wrong and you know how to solve it, you are ready to figure out how to put it in your code without breaking everything. Here is my process:

  1. Rely on the cascade
  2. Use vendor prefixes
  3. Use * and _ hacks for IE6 & 7
  4. Almost never use \9 for IE8
  5. Know when to quit trying to hack IE
  6. Never use hacks to target the latest versions of Firefox, Chrome, or Safari.

That’s a lot to take in, so I’ll detail each one below.

Rely on the Cascade

First, rely on the cascade whenever possible. CSS has a natural system of fallbacks built right in. Browsers take into account the last value that they were able to understand (this is how the cascade was designed to work). This means that if you order different solutions to the same problem from least advanced to most advanced, browsers will naturally use the most advanced solution they are capable of understanding. For example:

.foo{
  background-color: #ccc; /* older browsers will use this */
  background-color: rgba(0,0,0,0.2); /* browsers that understand rgba will use this */
} 

Use vendor prefixes

The next tool you want to employ is vendor prefixes. They allow you to give different values to different browsers, particularly for properties that haven’t stabilized.

background: #1e5799; /* Old browsers */
background: -moz-linear-gradient(top, #1e5799 0%, #2989d8 50%, #207cca 51%, #7db9e8 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#1e5799), color-stop(50%,#2989d8), color-stop(51%,#207cca), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* IE10+ */
background: linear-gradient(top, #1e5799 0%,#2989d8 50%,#207cca 51%,#7db9e8 100%); /* W3C */

Notice the two syntaxes for webkit. Just like normal property fallbacks, vendor prefixes should be ordered from oldest version to newest so that each browser gets the best code it is capable of handling.

If there is a standard syntax, you want to put that last so that as support for the standard increases, more and more browsers will use the best code. This is marked with a comment “W3C” in the above code.

Use * and _ hacks for IE6 & 7

When you have identified specific IE bugs, and you know how you want to work around them, use _ and * hacks to target that particular browser. For example:

.clearfix {
  overflow: hidden; /* new formatting context in better browsers */
  *overflow: visible; /* protect IE7 and older from the overflow property */
  *zoom: 1; /* give IE hasLayout, a new formatting context equivalent */
}

All IE hacks target a particular browser and everything before it, so for example:

  • _ targets IE6 and older
  • * targets IE7 and older, and
  • \9 targets IE8 and older UPDATE: IE9 is also targeted for certain properties.

That means that when you use multiple hacks you need to put them in order; underscore, then star, then \9.

Almost never use \9 for IE8

That said, I have not really needed to use \9 for any browser quirks in IE8. I use it simply to fill in the gaps when there is a difference in support. For example, if I’m using a box-shadow in better browsers, and the box looks weird without anything around it in IE8, I’ll use \9 to add a border for that browser. The cascading technique wouldn’t work in this case, because the backup method is applied to a different property.

Know when to quit trying to hack IE

Don’t try to make everything exactly the same in IE. It is important to think about what is in the best interest of each set of users. Do you waste another several HTTP requests, extra HTML, JS, and additional CSS to force rounded corners to work in IE6-8? For me, the answer is a clear “No.”

It is important to know when to give up on a particular feature. For example, don’t use filters to simulate css3 gradients. They cause performance issues and layout bugs. It is best to avoid the desire to make your site exactly the same in every single browser regardless of capability. Users of IE 6-8 are much better off with a simplified experience (not broken, just simpler) that with a site that rolls out all the bells and whistles using a ton of polyfills, but is incredibly slow.

For example, avoid the following code to duplicate the gradient from the example above.

filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#1e5799', endColorstr='#7db9e8',GradientType=0 ); /* IE6-9 */

Never use hacks to target the latest versions of Firefox, Chrome, or Safari.

Finally, if you think you need to hack to serve different code to Firefox, Chrome, or Safari — something has gone very awry. It makes sense to go back and look at what you’ve written to see if you are going against the grain of CSS.

Do you have particular techniques for debugging CSS? Or for implementing fixes once you’ve found a solution? I’d love to hear more about it in the comments.

If you would like to read this post in spanish, click here.

Code formatting for CSS Gradients

I may have found a way to format CSS3 Gradients that doesn’t make my eyes bleed. Yippee!

I was talking to @glan the other day about CSS3 gradients. We were discussing how to break them down into understandable layers and the difficulties when things you need to know about may be split across multiple properties. At the same time, I was checking out these cool CSS Coding Standards shared by @csswizardry, and I started wondering if formatting the code for CSS gradients could make them easier to understand.

I grabbed one of Lea Verou’s CSS3 gradient patterns as a starting point. They are insane and amazing and mind blowing. If you haven’t checked them out, you totally should. Anyway, I grabbed the code from the arrows example to try out different formatting options.

Option A – One line per property value pair

Let’s start off with the standard one line per property value pair.


.arrows {
	background: linear-gradient(45deg, #92baac 45px, transparent 45px), linear-gradient(45deg, #92baac 45px, transparent 45px)64px 64px, linear-gradient(225deg, transparent 46px, #e1ebbd 46px, #e1ebbd 91px, transparent 91px), linear-gradient(-45deg, #92baac 23px, transparent 23px, transparent 68px,#92baac 68px,#92baac 113px,transparent 113px,transparent 158px,#92baac 158px);
	background-color:#e1ebbd;
	background-size: 128px 128px;
}

Ok, awful, right?

Option B – Line return for each gradient

Let’s try adding a line return for each linear gradient.


.arrows {
	background: 
	linear-gradient(45deg, #92baac 45px, transparent 45px), 
	linear-gradient(45deg, #92baac 45px, transparent 45px)64px 64px, 
	linear-gradient(225deg, transparent 46px, #e1ebbd 46px, #e1ebbd 91px, transparent 91px), 
	linear-gradient(-45deg, #92baac 23px, transparent 23px, transparent 68px,#92baac 68px,#92baac 113px,transparent 113px,transparent 158px,#92baac 158px);
	background-color:#e1ebbd;
	background-size: 128px 128px;
}

Option C – Tab per value

The last example was better, but I could kind of see a pattern in it, so next, I tried formatting it like a table with tabs to separate the columns.


.arrows {
	background: 
	linear-gradient(45deg,	#92baac		45px,	transparent	45px), 
	linear-gradient(45deg,	#92baac		45px,	transparent	45px)	64px		64px, 
	linear-gradient(225deg,	transparent	46px,	#e1ebbd		46px,	#e1ebbd		91px,	transparent	91px), 
	linear-gradient(-45deg,	#92baac 	23px,	transparent	23px,	transparent	68px,	#92baac 	68px,	#92baac	113px,	transparent	113px,	transparent	158px,	#92baac	158px);
	background-color: #e1ebbd;
	background-size: 128px 128px;
}

I wanted to like this option, I really did, but you have things lining up that aren’t the same kind of values and that feels weird.

Option D – Line return per color stop

So next, I thought I’d try adding a line return at every comma (thus every color stop).


.arrows {
	background: 
		linear-gradient(
			45deg, 
			#92baac 45px, 
			transparent 45px
		), 
		
		linear-gradient(
			45deg, 
			#92baac 45px, 
			transparent 45px
		) 64px 64px, 
		
		linear-gradient(
			225deg, 
			transparent 46px, 
			#e1ebbd 46px, 
			#e1ebbd 91px, 
			transparent 91px
		), 
		
		linear-gradient(
			-45deg, 
			#92baac 23px, 
			transparent 23px, 
			transparent 68px,
			#92baac 68px,
			#92baac 113px,
			transparent 113px,
			transparent 158px,
			#92baac 158px
		);
	background-color:#e1ebbd;
	background-size: 128px 128px;
}

Usually I write in a quite compressed style, but I find myself preferring to look at Option D.

What do you think? Would you vote for A, B, C, or D? Do you have a different way of formatting that works well for you?

UPDATE: Don’t forget to add a pre tag around your example code if you include it in the comments.

Scope donuts

Note: This article is esoteric-could-be-should-be wishing for future browsers. If you only like to hear about what you can use right now, you won’t like this. You’ve been warned. ;)

At first, when the HTML5 working group added the scope attribute I was skeptical. I thought, “oh dear, this is going to be another way for developers to cause massive duplication and inconsistency.” I still do worry, but I’m more excited about the tool and hoping we can also find really great things to do with it.

Scope is great for mashups

The first that comes to mind, and the reason it was created, is mashups. Imagine you want to pull in a twitter feed or a video into your page. Unless you intend to rewrite it all (and often widgets block such fine grained control), you’ll probably be allowing someone else’s CSS onto your page. That can be daunting to say the least.

For example, the twitter widget I use pulls in ~1.36kb of CSS that could potentially interfere with my site styles — and it does it via JavaScript, so unless I’m ready to switch to using the API rather than a widget, I’m stuck allowing their styles on my page.

The way to sandbox those styles today is to be sure each style starts with a twitter specific class name. You can see from their code that they did a very good job of it. None of their styles will be polluting mine. Unfortunately, not all widget CSS will be so enlightened (especially not ad code). HTML5 offers another option for allowing authors to sandbox styles called the scope attribute. David Storey has a much better explaination of scope on his blog, I’ve adapted this example from his:

<div>
  <style scoped>
    p { color: blue; }
  </style>
  <p>The text in this paragraph will be blue</p>
  <p>And in this paragraph too</p>
</div>
<p>This paragraph is out of scope so will be gray</p>

If your browser supports it, it will look like this:

The text in this paragraph will be blue

And in this paragraph too

This paragraph is out of scope so will be gray

There are a lot of really great use cases for this, widgets, ads, even large companies with multiple teams putting functionality on a single page. On the other hand, there is a use case for which it falls flat: components. I’d love to see it extended so it could work for both.

Scope is more than a starting point, it’s a donut

donuts
Donuts by mamaloco

The interesting thing about UI components (different than ads or widgets) is that they can sometimes contain other unrelated components. You can have a tabset that contains headings, paragraphs, media blocks, or even (holy ugly!) another tabset. Ideally, you would scope the CSS of the tabset to the tabs only, so it can’t bleed outward and change styles on the rest of the page, but you also want to prevent the styles from bleeding inward to content components. So we need a way of saying, not only where scope starts, but where it ends. Thus, the scope donut. The styles affect the donut shape, but not the other components which can be found in the donut hole.

Tabs from the admin section of Let's Freckle, a time tracking app.
Figure 1: Tabs from Let’s Freckle, a time tracking software.

It has always struck me as odd that scope is declared in the HTML, because ideally with reusable components you wouldn’t want to repeat that code all over the place. Each of the tabs has different content related to my Freckle settings. The content styles aren’t specific to the tabs, but may also be used in other parts of the page. We want to make that reuse possible, by keeping our tabs from affecting the way content (the components in the donut hole) components look. I’d like to do this once, in the CSS, and then have it apply anywhere the component is used.

The first step is to be able to define that component, including both it’s HTML and CSS. Let’s start with a basic box. It’s HTML might look something like this:

<div class="box tabs"> 
    <div class="hd">
    	  Box Header
    </div>
    <div class="bd">
        Box Body
    </div>
</div>

The scope of a box begins at the wrapper div with the class box, and ends at the box body. We don’t for example want the styles on the box spilling over into whatever content we put in the box. I’m not sure how exactly to say this in CSS, but I like the idea that using nested selectors implies meaning about the relationship of those parts. e.g. nesting the selectors means that the sub nodes belong to the same component.

In other words, if I applied a text color to my box, it would change the color of text in the header, but not to subnodes in the body. Let’s take a look at an example syntax. I don’t really know what the right syntax is, but I’m more and more convinced it is worth finding a syntax to express it.

.box {
    border: 1px solid gray;
    color: red; // would cause text in the header to be red, but not inside the body.
    scope: start; 
    & .hd {
        border-bottom: 1px solid gray;
    } 
    & .bd {
        scope: end;
    }
}

This basically says that hd and bd belong to the box object and that the scope of these styles starts at .box and ends at .bd. It prevents styles from bleeding either up or down. Note: I do wonder if we need to say where it starts given that the nature of CSS is that it is namespaced to wherever the selector begins. It also makes me wonder why in the world scope is in the HTML rather than the CSS. It seems oddly out of place. Moving on…

There are several ways to mark up tabs, but let’s assume the HTML of the tabs component looks like this:

<div class="box tabs"> 
    <div class="hd">
        <ul class="tabControl">
            <li><a href="#">Personal</a></li>
            <li><a href="#">Date & Time</a></li>
            <li class="current"><a href="#">Password</a></li>
            <li><a href="#">API</a></li>
            <li><a href="#">Timer</a></li>
            <li><a href="#">Rounding</a></li>
        </ul>
    </div>
    <div class="bd">
        <ul>
            <li class="tab-bd">Tab 1 Content</li>
            <li class="tab-bd">Tab 2 Content</li>
            <li class="tab-bd current">Tab 3 Content</li>
            <li class="tab-bd">Tab 4 Content</li>
            <li class="tab-bd">Tab 5 Content</li>
            <li class="tab-bd">Tab 6 Content</li>
        </ul>
    </div>
</div>

What you can see is that tabs are an extension of an ordinary box. They have a head and body wrapped in a div with the classes box and tabs. What makes the tabs unique is that both the head and body are filled with unordered lists which correspond to the tab control and tab body respectively.

Tabs with the donut highlighted
Figure 2: Tabs with the donut highlighted. We don’t want any styles falling either into the donut hole. This where scope ends. (See? It’s donut colored! Forgive me, this diagram is very very ugly.)

We could try to express the next bit by combining three tools:

  • nesting for defining the component structure,
  • extends so we don’t need to repeat anything we already know about boxes in the code for tabs, and
  • a new property “scope” which tells the browser where to stop allowing styles to bleed down.
.tab {
    extends: .box; // so inherits the starting scope 
    & .tab-bd {
        scope: end;
    }
}

So, any styles for tabs should only apply to the nodes between the start and end of scope, or between .box and .tab-bd. Is this the right syntax? I’m not sure actually, but I tend to like it.

The region we want to apply styles to.
Figure 3: the region we want styles to apply to.

Figure 3 sums up what I’m asking for — a way to apply styles only to the divs which make up my object and not to content that simply happens to be inside it. You can do that today with careful use of style and the child selector “>”, but in a world where some content is trusted more than other content, it might be easier to just be able to say explicitly which donut of elements I want a particular set of styles to apply to.

You may have heard the Henry Ford quote:

If I’d asked customers what they wanted, they would have said “a faster horse”.

Henry Ford

I think lots of us want *way* more than just a faster horse. :)

What do you think? Useful? I’ve been holding on to this post for four months because I wasn’t sure about it, because it is quite different from how things work now, but I thought I’d put it out there and see what other people think.