You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>After Raj's <ahref="contacts-widget.html">discovery of Shadow DOM</a> triggered company-wide conversion to properly incapsulated widgets, Howard—not to be outdone—gleans another great opportunity in this change. He realizes that with the help of <ahref="http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#attr-style-scoped">scoped stylesheets</a> and <ahref="../spec/shadow/index.html">shadow DOM</a>, he can separate the general framing of the widgets from the theming code. For years now, it's been bugging him that whenever the widget's author wanted to tweak the general layout of their widgets, they would have edit the <code>/src/ui/layout/widgets.css</code> stylesheet and muck with their gubbins of code there, creating a waterfall of lines that looks like this:<p>
<ins>// Styles moved from /src/ui/layout/widgets.css, minus ".contacts.widget" selector.</ins>
92
+
<ins>// Quasi-literals are awesome! (<ahref="http://wiki.ecmascript.org/doku.php?id=harmony:quasis">http://wiki.ecmascript.org/doku.php?id=harmony:quasis</a>)</ins>
<p>Whoa!—Howard sees another way to improve robustness of the layout system. The <ahref="../spec/shadow/index.html#api-shadow-root-apply-author-styles"><code>applyAuthorStyles</code></a> flag (which is <code>false</code> by default) controls whether document stylesheets apply in the shadow DOM subtrees. Thus removing a line of code ensures that the widget's styles are never messed with:</p>
115
111
112
+
<preclass="prettyprint"><code>
113
+
this.element.className = 'contacts widget';
114
+
var shadow = new ShadowRoot(this.element);
115
+
<del>shadow.applyAuthorStyles = true;</del>
116
+
var users = shadow.appendChild(document.createElement('ul'));
117
+
</code></pre>
116
118
119
+
<p>The celebration is cut short as Howard notices that the stylesheets from <code>/src/ui/themes/</code> directory were <em>also</em> part of the document stylesheet. As it stands, there is no way to apply theming styles to the widgets…</p>
117
120
121
+
<p>Or maybe there is. <ahref="http://dev.w3.org/csswg/css-variables/">CSS Variables</a> to the rescue! Upon reading the spec, Howard does a little dance. Not only they allow widget theming, the <em>method</em> is such that you can specify <strong>precise</strong> and <strong>named</strong> points where theming is allowed. Digging into the Contacts widget, Howard documents the following theming points:</p>
122
+
<ul>
123
+
<li><strong>font</strong> -- font and size of text</li>
124
+
<li><strong>color</strong> -- color, used for text and border of the user pic</li>
125
+
<li><strong>background</strong> -- style of the widget background</li>
126
+
</ul>
127
+
<p>Howard mixes the variables into the <code>scopedStyleText</code> string:</p>
118
128
129
+
<preclass="prettyprint"><code>
130
+
// Styles moved from /src/ui/layout/widgets.css, minus ".contacts.widget" selector.
131
+
// Quasi-literals are awesome! (<ahref="http://wiki.ecmascript.org/doku.php?id=harmony:quasis">http://wiki.ecmascript.org/doku.php?id=harmony:quasis</a>)
132
+
Contacts.prototype.scopedStyleText = `ul {
133
+
margin: 0;
134
+
list-style: none;
135
+
<ins>font: data(font);</ins>
136
+
<ins>color: data(color);</ins>
137
+
<ins>background: data(background);</ins>
138
+
…
139
+
}
140
+
ul li { … }
141
+
ul li img.photo {
142
+
border: 1px solid<ins> data(color)</ins>;
143
+
…';
119
144
145
+
</code></pre>
120
146
147
+
<p>Now to tweak the actual themes, starting with <code>/src/ui/themes/purple-and-black.css</code>:</p>
121
148
149
+
<preclass="prettyprint"><code>
122
150
151
+
…
123
152
153
+
/* Contacts Widget Theme */
124
154
155
+
<del>.contacts.widget ul {</del>
156
+
<del>color: black;</del>
157
+
<del>background: purple;</del>
158
+
<del>}</del>
125
159
160
+
<del>.contacts.widget ul li img.photo {</del>
161
+
<del>border-color: black;</del>
162
+
<del>}</del>
126
163
164
+
<ins>.contacts.widget {</ins>
165
+
<ins>data-color: black;</ins>
166
+
<ins>data-background: purple;</ins>
167
+
<ins>}</ins>
127
168
169
+
…
128
170
171
+
</code></pre>
129
172
173
+
<p>Whoohoo! No more reaching into widgets to style them! No more breakages when widget authors change their widgets and forget to update the theme! After all themes are converted, the <em>Socia1eet</em> looks and works same as before. But on the inside, the brittle layout and theming system has been replaced with a flexible, elegant, and robust solution.</p>
0 commit comments