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
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+7-5
Original file line number
Diff line number
Diff line change
@@ -60,9 +60,9 @@ In this phase we validate Block syntax and will stop the build with a helpful er
60
60
61
61
At the end of a successful __Block Parsing Phase__, we are left with a collection of `Block` objects that my be used to query any and all relevant information about a Block file. Any valid `Block` may contain one to many `Style` objects that represent individual `BlockClass`es, or `AttrValue`s accessible on the `Block`. These in turn map directly back to one or more declared rulesets in the source Block file.
62
62
63
-
You can read more about `Block` objects and their associated APIs in the [Block Object README](./packages/css-blocks/src/Block/README.md).
63
+
You can read more about `Block` objects and their associated APIs in the [CSS Blocks Core README](./packages/css-blocks/README.md).
64
64
65
-
## Template Analysis
65
+
## Template Analysis
66
66
Once we're finished constructing our `Block` objects, these data are passed off to a template `Analyzer` for the __Template Analysis Phase__. It is the job of the analyzer to inspect every element, in every template of the application, and report back information, like:
67
67
68
68
- which styles are used;
@@ -102,7 +102,7 @@ As described in the [CSS Blocks README][CORE], `Style` objects (`BlockClasses` a
102
102
103
103
> Note: BEM is the default output mode for css-blocks – and currently the only output mode – but [other output modes](./packages/css-blocks/src/configuration/OutputMode.ts) for css-blocks may be added in the future.
104
104
105
-
## Optimization (Production Only)
105
+
## Optimization (Optional)
106
106
Once we have all of our style data parsed from the __Block Parsing Phase__, and all of our usage data from the __Template Analysis Phase__, *and* the compiled Block CSS files, all this information is passed off to [Opticss][OPTICSS], our standalone CSS stylesheet optimizer, for style optimization!
107
107
108
108
I encourage you to read up about Opticss and its internals [over in its repository][OPTICSS]. However, after all is said and done, and a lot of optimization magic is run, we are returned:
@@ -111,7 +111,7 @@ I encourage you to read up about Opticss and its internals [over in its reposito
111
111
2. a `StyleMapping` object with queryable rewrite data, described below;
112
112
3. an `Action` queue describing every transformation step the optimizer made.
113
113
114
-
> Note: In development mode, this step is essentially a pass through. The Optimizer will return un-transformed CSS and `StyleMapping` data that is the same as the input data.
114
+
> Note: In a non-optimized build, this step is essentially a pass through. The Optimizer will return un-transformed CSS and `StyleMapping` data that is the same as the input data.
115
115
116
116
The [`StyleMapping`](./packages/css-blocks/src/TemplateRewriter/StyleMapping.ts) object returned by css-blocks after an Opticss run contains APIs that allow you to query a `RewriteMapping` for any Element analyzed during the __Analysis Phase__. This `RewriteMapping` contains all the information required to rewrite that Element from the old, pre-optimized classes, to the new, fully-optimized classes, as we will see in the __Rewrite Phase__.
117
117
@@ -190,7 +190,9 @@ const el2Classes = [
190
190
].join('');
191
191
```
192
192
193
-
> Note: The above functional syntax is only here to explain the concept of `RewriteMapping`s and conditional style application! Please read about css-blocks' [Runtime Library][RUNTIME] to learn about how this dynamicism is actually represented in the browser.
193
+
> ⁉️ **Note**
194
+
>
195
+
> The above functional syntax is only here to explain the concept of `RewriteMapping`s and conditional style application! Please read about css-blocks' [Runtime Library][RUNTIME] to learn about how this dynamicism is actually represented in the browser.
194
196
195
197
In production mode however, these `RewriteMapping`s change! The optimized stylesheet may look something like this:
Copy file name to clipboardExpand all lines: OLD_README.md
+6
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,12 @@
1
1
CSS Blocks
2
2
==========
3
3
4
+
**ATTENTION:** This is the original README that Chris wrote for for this project.
5
+
Much of it was written before the features it talks about even existed. Some of those
6
+
features still do not exist, and of those, some may never exist. We're in the process
7
+
of removing this file, you probably want to be reading the [README](./README.md) instead.
8
+
9
+
-------
4
10
CSS Blocks are a way of writing highly decoupled and isolated styles that can be statically analyzed and optimized for delivery and runtime performance.
5
11
6
12
In a component-oriented web application there's one pillar of web technology that doesn't quite seem to fit: Cascading Style Sheets. The goals of components are to create strong boundaries and isolated behaviors that can be composed without tight coupling. CSS is global and the desire to create visual consistency across an application seems at odds with the goal of isolation. What's more, techniques that produce styles that are kept in isolation have been at odds with browser performance: highly specific and scoped selectors have performance issues, class name mangling is bad for gzip compression, inline styles are slow, and mixins, while useful for sharing styles consistently into components, produce bloated output.
Copy file name to clipboardExpand all lines: README.md
+32-17
Original file line number
Diff line number
Diff line change
@@ -31,9 +31,14 @@ But, most importantly, CSS Blocks is **⚡️Statically Analyzable**.
31
31
## The ⚡️ of Static Analysis
32
32
Static analysis means css-blocks can look at your project and know with *certainty* that any given CSS declaration will, will not, or might under certain conditions, be used on any given element in your templates.
33
33
34
-
This determinism lets us supercharge your CSS build with powerful stylesheet optimization via [Opticss](https://github.com/css-blocks/opticss), and other developer delight features that other CSS frameworks have, as of yet, been unable to provide.
34
+
Most stylesheet architectures have to walk a fine line between performance and
35
+
maintainability. Tilt too far in either direction and either your users or the developers
36
+
will end up paying the cost. With CSS Blocks, you can focus on making sure your
37
+
stylesheets are easy to maintain as your application changes, and with the new
38
+
CSS optimizer, [OptiCSS](https://github.com/css-blocks/opticss), the small size of your
39
+
app's production stylesheets after compression will amaze you.
35
40
36
-
That means you get to write ergonomic, vanilla, scoped CSS – and let the build take care of making your stylesheets screaming fast and fantastically small.
41
+
Gone are the days where you spend several minutes debugging your app only to discover a subtle typo that caused a selector to not match – CSS Blocks will give you a build error and suggest possible fixes. With IDE integration, projects using CSS Blocks will be able to quickly navigate to selector definitions that match your current template element and find which template elements match your current selector, autocomplete class names. With CSS Blocks new resolution system, cascade conflicts will be caught for you before you even know they exist and you will never have to fight a specificity war ever again.
37
42
38
43

39
44
@@ -99,9 +104,9 @@ Typically, a single Block will contain styles for a particular component or conc
99
104
A Block file may contain:
100
105
101
106
## The Scope Selector
102
-
The scope ruleset contains styles applied to the root of the scoped style subtree. All other elements assigned styles from a Block must be contained in the subtree of the Block's root. We use the special [`:scope` pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) to represent these styles.
107
+
The scope ruleset contains styles applied to the root of the scoped style subtree. All other elements assigned styles from a Block must be contained in the document subtree of an element assigned to the block's :scope. We use the special [`:scope` pseudo-class](https://developer.mozilla.org/en-US/docs/Web/CSS/:scope) to represent these styles.
103
108
104
-
The `:scope` selector may contain the special `block-name` property so you may provide your own Block name for easy debugging and BEM class generation. If no `block-name` is provided, we will try to infer the Block name from the file name
109
+
The `:scope` selector may contain the special `block-name` property so you may provide your own Block name for easy debugging and BEM class generation. If no `block-name` is provided, we will infer the Block name from the file name.
105
110
106
111
> 💡 **Feature Note: Block Names**
107
112
>
@@ -116,7 +121,7 @@ The `:scope` selector may contain the special `block-name` property so you may p
116
121
```
117
122
118
123
## Class Selectors
119
-
Blocks may can contain other classes that may be applied to elements inside the scoped style sub-tree. These are literally class selectors! They are local to that Block and isolated from all other similarly named classes in other Blocks.
124
+
Blocks may can contain other classes that may be applied to elements inside the scoped style sub-tree. These are just class selectors, but they are local to that Block and isolated from all other similarly named classes in other Blocks.
120
125
121
126
```css
122
127
.sub-element { /* ... */ }
@@ -126,7 +131,7 @@ Blocks may can contain other classes that may be applied to elements inside the
126
131
Together, the `:scope` selector and all declared `.class` selectors define the full interface of stylable elements available to a Block's consumer.
127
132
128
133
## State Selectors
129
-
States represent a mode or interaction state that the `:scope` or a class – call the state's **originating element** – may be in. States are written as attribute selectors with the special `state` namespace.
134
+
States represent a mode or interaction state that the `:scope` or a class – called the state's **originating element** – may be in. States are written as attribute selectors with the special `state` namespace.
130
135
131
136
```css
132
137
:scope { /* ... */ }
@@ -136,8 +141,14 @@ States represent a mode or interaction state that the `:scope` or a class – ca
136
141
.sub-element[state|is-active] { /* ... */ }
137
142
```
138
143
144
+
> **⁉️ What the pipe is going on here?**
145
+
>
146
+
> Once upon a time, developers fell in love with XML and thus was born xhtml, a flavor of HTML that allowed HTML elements to be mixed together with elements from other XML syntaxes like SVG and MathML. CSS went along for the ride and so, while many have never seen or used the feature, CSS has support for namespaced elements and attributes. In CSS, the `|` symbol is used to delimit between a namespace identifier (assigned by the `@namespace` at-rule) and the element or attribute name (also called a [qualified name](https://drafts.csswg.org/css-namespaces-3/#css-qualified-name)).
147
+
>
148
+
> In markup, instead of a pipe symbol, the colon is used to delimit a namespace identifier and a qualified name. Yes, this is confusing -- but we don't make CSS syntax, we just use it.
149
+
139
150
## Sub-State Selectors
140
-
States on the `:scope` selector or a class selector may contain sub-states for more granular styling. Sub-states of a State are **mutually exclusive** and an element may only be in one sub-state at any given time.
151
+
States on the `:scope` selector or a class selector may contain sub-states for more granular styling. Sub-states of a State are **mutually exclusive** and an element may only be in one sub-state of that state at any given time.
141
152
142
153
```css
143
154
:scope { /* ... */ }
@@ -170,7 +181,7 @@ CSS Blocks implements a **strict subset of CSS**. This means we've intentionally
170
181
171
182
### 🚨 However:
172
183
173
-
-`!important` is **forbidden**
184
+
-`!important` is **forbidden** – you won't be needing it!
174
185
- The `tag`, non-state `[attribute]`, `#id` and `*` selectors are **forbidden** (for now!)
175
186
- The [Logical Combinators](https://www.w3.org/TR/selectors-4/#logical-combination)`:matches()`, `:not()`, `:something()` and `:has()` are **forbidden** (for now!)
176
187
- Selectors must remain **shallow**.
@@ -201,7 +212,7 @@ In css-blocks, **shallow selectors** mean:
#### 3) The Sibling Combinators' ("[+](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors)", "[~](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors)") context selector must target the **same class** used in the key selector.
215
+
#### 3) The Sibling Combinators' ("[+](https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors)", "[~](https://developer.mozilla.org/en-US/docs/Web/CSS/General_sibling_selectors)") context selector must target the **same class or `:scope`** used in the key selector.
205
216
206
217
```css
207
218
/* ✅ Allowed! */
@@ -239,7 +250,7 @@ However, whatever the implementation is, it will feel as though you're interfaci
239
250
```
240
251
241
252
```hbs
242
-
{{!-- :scope selector is automagically applied to the template's wrapper element. Thanks Glimmer! --}}
253
+
{{!-- :scope selector is automagically applied to the template's root-level element. Thanks Glimmer! --}}
> Whether you're integrating with a 3rd party library, or pulling in dependencies internal to your company, at some point you'll want to integrate with styles delivered via NPM! The resolution logic for `@block-reference`s to `node_modules` hasn't yet been implemented yet, but you can track progress (or even help out!) [over on Github]().
285
296
286
297
With the above code, `block-2` now has a local reference `other-block` which points to `block-1`. We can now freely use the `other-block` identifier inside of `block-2` when we want to reference reference `block-1`. This comes in handy! Especially with features like:
287
298
299
+
# Object Oriented CSS
300
+
288
301
## Block Implementation
289
302
A Block's public interface is defined by the states and classes it styles. A Block may declare that it implements one or more other referenced Blocks' interfaces, and the compiler will ensure that all the states and classes it defines are also in the implementing Block! In this way, the compiler can guarantee it is safe to use different Blocks to style the same markup in a component.
290
303
@@ -366,12 +379,13 @@ Instead, we can simply extend the `<basic-form>` Block, and only apply the small
366
379
>
367
380
> The `extends` property is only available in the `:scope` selector. If you use it in any other selector, it will be ignored.
368
381
369
-
An extending block is able to re-define any property on any style it inherits from. Styles defined in the extending block will **always** take priority over the definitions
382
+
An extending block is able to re-define any property on any style it inherits from. CSS declarations defined in the extending Block will **always** take priority over the definitions inherited by the same named Style in the base Block.
370
383
371
384
> 🔮 **Future Feature: Extension Constraints**
372
385
>
373
386
> Sometimes, properties inside of a component are **so** important, that authors may want to constrain the values that extenders and implementors are able to set. In the near future, css-blocks will enable this use case through the custom `constrain()` and `range()` CSS functions. You can come help out over on Github to make this happen faster!
374
387
388
+
# Style Composition
375
389
## Block Paths
376
390
As your Blocks begin interacting with each other in increasingly complex ways, you will find yourself needing to reference specific classes or states on another Block, as you'll see later in this document. You do this using a small query syntax called a [Block Path](./packages/css-blocks/src/BlockSyntax/BlockPath.ts).
377
391
@@ -513,14 +527,15 @@ Here, we tell css-blocks to use the `color` value from `other.selector` instead
513
527
}
514
528
```
515
529
516
-
### Resolve All Shorthand
517
-
For straightforward resolutions where you just want to yield or assume full control of styling against another block, feel free to use the CSS `all` property to quickly override or yield to all property conflict with another block:
530
+
> 🔮 **Future Feature: Resolve All Shorthand **
531
+
>
532
+
> For straightforward resolutions where you just want to yield or assume full control of styling against another block, feel free to use the CSS `all` property to quickly override or yield to all property conflict with another block:
518
533
519
-
```
534
+
```css
520
535
.my-class {
521
536
color: red;
522
537
background: blue;
523
-
538
+
524
539
/* Yields all conflicts to `other.selector` */
525
540
all: resolve("other.selector");
526
541
}
@@ -553,7 +568,7 @@ So, continuing with the example from the previous section – **Composition in
553
568
554
569
Here we have told css-blocks that when our component's `.button` class is used with hoverable's `.button` class, we want our component's style declarations to win! We have declared an **override resolution** for both properties.
555
570
556
-
If we were to switch around the order a bit so our `background-color` resolution comes *after* our component's declaration, it means that when these two classes are used together, hoverable's `.button` class will win!
571
+
If we were to switch around the order a bit so our `background-color` resolution comes *after* our component's declaration, it means that when these two classes are used together, hoverable's `.button` class will win, but only for that property. This is why you will never have to fight the cascade or use `!important` ever again!
0 commit comments