-
Notifications
You must be signed in to change notification settings - Fork 14
/
element-queries.bs
1118 lines (923 loc) · 47.2 KB
/
element-queries.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class=metadata>
Title: CSS Element Queries [Level 1]
Shortname: elementqueries
Level: 1
Status: DREAM
URL: https://github.com/tomhodgins/element-queries-spec
Repository: tomhodgins/element-query-spec
Editor: Tommy Hodgins, tomhodgins@gmail.com
Abstract: Element Queries allow authors to test and query values or features of elements in an HTML document. They are used in the CSS @element rule to conditionally apply styles to a document, and in various other contexts and languages, such as HTML and JavaScript.
Abstract:
Abstract: CSS Element Queries [Level 1] describes the mechanism and syntax of scoped stylesheets and element queries, the responsive conditions. It also describes the meta-selectors, functions, and units that make element queries powerful.
Logo: <img src=http://elementqueries.com/eqcss-logo.png style=width:100px;>
</pre>
<h2 id=introduction>Introduction</h2>
By default all CSS is written from the global scope ('':root'', or the HTML element), and ''@media'' queries apply globally to all elements based on the conditions of the browser and media.
The idea of a scoped stylesheet is to allow CSS to view a rule, or multiple rules from the perspective of any element in the document as though it was '':root''.
Just like CSS already has ''@media'' queries which help define styles for different media conditions, this document describes functionality for an ''@element'' query syntax to define styles that target elements more specifically with conditions based on their own properties.
<h3 id=values>Values</h3>
Value types not defined in this specification, such as <<integer>>, <<dimension>>, <<ratio>>, and <<ident>> are defined in [[!CSS3VAL]], and [[!MEDIAQUERIES-4]]
<h3 id=units>Units</h3>
The units used in element queries are the same as in other parts of CSS, as defined in [[!CSS3VAL]]. For example, the pixel unit represents CSS pixels and not physical pixels.
Additionally, new <a href=#element-percentage-units>element-percentage units</a> are defined in this document which relate to an element's own width and height dimensions.
<h2 id=element-queries>Element Queries</h2>
An <strong>element query</strong> is a method of testing certain aspects of an element and applying styles based on whether that test returns true or false.
The syntax of an element query consists of a <<selector-list>>, plus an optional list of zero or more responsive conditions, followed by a stylesheet containing one or more CSS rules:
<pre class=railroad>
T: @element
N: selector list
Star:
And:
T: and
N: responsive condition
T: {
N: stylesheet
T: }
</pre>
A scoped stylesheet will return true as long as at least one (1) element in the document matches a selector in the <<selector-list>>.
An element query is a logical expression that is either true or false. An element query is true if:
<ul>
<li>at least one element in the document matches a selector in the <<selector-list>>
<li>all responsive conditions are true
</ul>
User agents must re-evaluate element queries in response to changes in the user environment that they're aware of, for example resizing the browser, clicking, or scrolling, depending on which responsive conditions are being evaluated, and change the styles applied accordingly.
Note: This specification does not currently define a list of events which trigger a style recalculation, or a syntax (in CSS, HTML, or JS) through which scoped stylesheets could be limited to specific events.
<h3 id=scoped-styles>Scoped Stylesheets</h3>
To write a scoped stylesheet write ''@element'', followed by any amount of whitespace. Wrap one or more comma-separated CSS <<selector>> (optionally wrapped in single (<code>'</code>) or double (<code>"</code>) quotes), followed by any amount of whitespace, and wrap one or more CSS rules in a pair of curly brackets (<code>{</code>,<code>}</code>).
<div class=example>
Example scoped stylesheet</strong>
<pre class=language-css>
@element html { ... }
</pre>
</div>
<h4 id=multiple-selectors>Multiple Selectors</h4>
You can include multiple CSS selectors in your scoped stylesheet by separating them with a comma and any amount of whitespace.
<div class=example>
Comma-separated selector list
<pre class=language-css>
@element ul, ol { ... }
</pre>
</div>
<h4 id=understanding-the-scope>Understanding the Scope</h4>
Any element on the page that matches a selector will apply the rules contained inside its scope to the page. The following examples will illustrate how the scope applies.
If we have two <code>div</code> elements in our HTML:
<pre class=language-html>
<div></div>
<div class=demo></div>
</pre>
<div class=example>
<pre class=language-css>
@element div {
div {
background: lime;
}
}
</pre>
In this example, because there are two <code>div</code> elements, both will match our scope and apply a rule saying all <code>div</code> elements have a green background.
</div>
<div class=example>
<pre class=language-css>
@element .demo {
div {
background: lime;
}
}
</pre>
In this example we have one element in our HTML with a class of <code>.demo</code>. Because of this, the rule applying to all <code>div</code> elements applies to both of the <code>div</code> elements in our HTML turning their background green.
</div>
<div class=example>
<pre class=language-css>
@element .demo {
.demo {
background: lime;
}
}
</pre>
In this example we have one element in our HTML with a class of <code>.demo</code>. Because of this, the rule applying to any elements with a class of <code>.demo</code> applies and turns the background of our <code>.demo</code> element green, leaving the other <code>div</code> untouched.
</div>
<div class=example>
<pre class=language-css>
@element div {
.demo {
background: lime;
}
}
</pre>
In this example, because there are two <code>div</code> elements, both will match our scope and apply a rule saying any element with a class of <code>.demo</code> will have a green background. This makes one of our <code>div</code> elements green and leaves the other untouched.
</div>
<div class=example>
<pre class=language-css>
@element select {
.demo {
background: lime;
}
}
</pre>
In this example we did not have any <code>select</code> elements in our HTML, so nothing will match our scope and no styles will be applied, leaving both of our <code>div</code> elements untouched.
</div>
It is possible for an element to match more than one ''@element'' query.
<h3 id=scoped-styles-with-repsonsive-conditions>Scoped Styles with Responsive Conditions</h3>
An element query is a scoped stylesheet with one or more responsive conditions added.
The following global CSS and scoped stylesheet are equivalent.
<div class=example>
Example of global CSS
<pre class=language-css>
body {
background: lime;
}
</pre>
</div>
<div class=example>
Example scoped stylesheet
<pre class=language-css>
@element html {
body {
background: lime;
}
}
</pre>
</div>
In both cases, as long as there is a <code>body</code> element inside of our <code>html</code>, it will have a green background.
We can also add a responsive conditions to our scoped stylesheets. To do this, write <code>and </code> followed by a responsive condition and value, separated by a colon (<code>:</code>) and wrapped in brackets (<code>(</code>,<code>)</code>).
<div class=example>
Example Element Query with Responsive Condition
<pre class=language-css>
@element html and (min-width: 500px) {
body {
background: lime;
}
}
</pre>
</div>
In this case, our element query is equivalent to the following media query, but not every element query will be able to be expressed as a media query.
<div class=example>
Example media query with responsive condition
<pre class=language-css>
@media (min-width: 500px) {
body {
background: lime;
}
}
</pre>
</div>
<h4 id=multiple-conditions>Multiple Conditions</h4>
You can add more than one responsive conditions to your element query. For this, include another <code>and</code>, followed by another responsive condition as before.
<div class=example>
Element query with multiple responsive conditions
<pre class=language-css>
@element html and (min-width: 500px) and (max-width: 1000px) {
body {
background: lime;
}
}
</pre>
</div>
Which in this case can be compared to the equivalent media query.
<div class=example>
Media query with multiple responsive conditions
<pre class=language-css>
@media (min-width: 500px) and (max-width: 1000px) {
body {
background: lime;
}
}
</pre>
</div>
In both cases when our <code>html</code> is between the sizes of <code>500px</code> and <code>1000px</code>, our <code>body</code> will have a green background.
<h4 id=combining-element-and-media-queries>Combining ''@element'' and ''@media'' queries</h4>
It's possible to combine the use of scoped stylesheets or element queries with media queries. Most of the time we combine them we want to include the media query on the inside of the element query. This will mean any time the element query is true, that media query will be visible to the browser and apply.
<div class=example>
Nesting a media query inside an element query
<pre class=language-css>
@element #headline and (min-characters: 20) {
@media print {
#headline {
border: 1px solid black;
}
}
}
</pre>
</div>
In this example, if the element with an ID of <code>#headline</code> has over 20 characters, it will display in print media with a thin black border.
<h4 id=self-referential-element-queries>Self-Referential ''@element'' queries</h4>
With element queries comes the new possibility that the rules you are applying when your responsive conditions are met will conflict with the responsive condition in your element query. In this situation we should not attempt to detect or handle these cases by ignoring certain styles, or checking whether any of the rules affect the validity of the responsive condition. It is best to apply the rule naïvely and allow the conflict to occur.
Note: The responsibility lies with the author to write ''@element'' queries which can be interpreted logically.
<div class=example>
<pre class=language-css>
@element .widget and (min‐width: 300px) {
:self {
width: 200px;
}
}
</pre>
</div>
In this example the query will only apply to elements with a class of <code>.widget</code> that are equal or wider than <code>300px</code>, and the rule sets a width on the same element which would make the rule no longer apply. Rather than trying to detect or intercept this behaviour and prevent it from happening, when the ''@element'' query applies to the document it will set the width to <code>200px</code>.
<h4 id=circular-referential-element-queries>Circular Referential ''@element'' queries</h4>
Another new possibility with element queries is having two or more queries that apply styles that match each others responsive condition. Just as with a self-referential ''@element'' query, we should not try to detect or ignore styles in this situation, and instead should compute the ''@element'' queries in the order they appear and apply the rules using normal CSS specificity.
<div class=example>
<pre class=language-css>
@element .widget and (min‐width: 400px) {
:self {
width: 200px;
}
}
@element .widget and (max‐width: 300px) {
:self {
width: 500px;
}
}
</pre>
</div>
In this example any element with a class of <code>.widget</code> that is equal to <code>400px</code> or wider will apply a rule setting the width of the same element to <code>200px</code>, which makes the following ''@element'' query valid. The second query sets a width of <code>500px</code> on the same element. In this case, even though the element now matches the responsive condition of the first query again, rather than get stuck in an infinite loop, we consider evaluation complete.
<h2 id=syntax>Syntax</h3>
Informal descriptions of the element query syntax appear in the prose and railroad diagrams of the previous sections. The formal element query syntax is described in this section, with the rule/property grammar syntax defined in [[!CSS3SYN]] and [[!CSS3VAL]].
<pre>
<dfn dfn-type=at-rule>@element</dfn> = @element <<eq-prelude>> { <<stylesheet>> }
<dfn dfn-type=type><eq-prelude></dfn> = <<selector-list>> | <<selector-list>> <<eq-condition>>*
<dfn dfn-type=type><eq-condition></dfn> = and ( <<eq-name>> : <<eq-value>> )
<dfn dfn-type=type><eq-name></dfn> = min-width | max-width | min-height
| max-height | min-characters | max-characters
| min-lines | max-lines | min-children
| max-children | min-scroll-y | max-scroll-y
| min-scroll-x | max-scroll-x | orientation
| min-aspect-ratio | max-aspect-ratio
<dfn dfn-type=type><eq-value></dfn> = <<integer>> | <<dimension>> | <<ratio>> | <<ident>>
<dfn dfn-type=selector>meta-selectors</dfn> = :self | :parent | :prev | :next
<dfn dfn-type=dfn>eq-unit</dfn> = ew | eh | emin | emax
</pre>
<h3 id=evaluating-element-queries>Evaluating Element Queries</h3>
Each <<eq-condition>> is associated with a boolean result, the same as the result of evaluating the specified responsive condition.
If the result of any responsive condition is used in any context that expects a two-valued boolean, "unknown" must be converted to "false".
Note: This means that, for example, when an element query is used in an @element rule, if it resolves to "unknown" it is treated as "false" and fails to match.
<h2 id=meta-selectors-in-css>Meta-Selectors</h2>
With element queries comes the need to target elements based on the scope we have defined. There are a number of new selectors that help target elements relative to the scope we have defined. These new selectors only work inside a scoped stylesheet and are called ''meta-selectors''.
<h3 id=diagram-of-meta-selectors>Diagram of ''meta-selectors''</h4>
Here is a diagram showing the relationship between the meta-selectors. The <a selector>:parent</a> is the parent element of <a selector>:self</a>, and <a selector>:prev</a> and <a selector>:next</a> represent the adjacent siblings to <a selector>:self</a>.
<pre style=text-align:center;>
<a selector>:parent</a>
↑
<a selector>:prev</a> ← <a selector>:self</a> → <a selector>:next</a>
</pre>
<dl dfn-type=selector dfn-for=meta-selectors>
<dt><dfn>:self</dfn>
<dd>
The <a selector>:self</a> meta-selector refers each element in the document that matches the root of our scoped stylesheet and any element query conditions it has.
<div class=example>
Example of <a selector>:self</a> meta-selector
<pre class=language-css>
@element .widget and (min-width: 200px) {
:self {
background: lime;
}
}
</pre>
In this case, any element with a class of <code>.widget</code> that is <code>200px</code> or wider will have a green background.
</div>
<dt><dfn>:parent</dfn>
<dd>
The <a selector>:parent</a> meta-selector refers to the element containing the element(s) in the root of our scoped stylesheet.
<div class=example>
Example of <a selector>:parent</a> meta-selector
<pre class=language-css>
@element .widget and (min-width: 200px) {
:parent {
background: lime;
}
}
</pre>
In this case, any element containing an element with a class of <code>.widget</code> that is equal or wider than <code>200px</code> will have a green background.
</div>
<dt><dfn>:prev</dfn>
<dd>
The <a selector>:prev</a> meta-selector refers to the sibling directly preceding the element at the root of our scoped stylesheet in the document.
<div class=example>
Example of <a selector>:prev</a> meta-selector
<pre class=language-css>
@element .widget {
:prev {
background: lime;
}
}
</pre>
In this case, any sibling coming directly before any element with a class of <code>.widget</code> will have a green background.
</div>
<dt><dfn>:next</dfn>
<dd>
The <a selector>:next</a> meta-selector refers to the sibling directly following the element at the root of our scoped stylesheet in the document.
<div class=example>
Example of <a selector>:next</a> meta-selector
<pre class=language-css>
@element .widget {
:next {
background: lime;
}
}
</pre>
In this case, any sibling coming directly after any element with a class of <code>.widget</code> will have a green background.
</div>
Note: the <a selector>:next</a> is similar to the selector: <code>:self + *</code>
</dl>
<h2 id=responsive-conditions>Responsive Conditions</h2>
All responsive conditions for ''@element'' queries are formatted as a condition name and value, separated by a colon (<code>:</code>) character, surrounded by brackets (<code>()</code>).
<pre class=railroad>
Star:
And:
T: and
T: (
N: condition name
T: :
N: value
T: )
</pre>
The following examples are all valid as <<eq-condition>>:
<div class=example>
<pre class=language-css>
(min-width: 500px)
</pre>
</div>
<div class=example>
<pre class=language-css>
(min-aspect-ratio: 16/9)
</pre>
</div>
<div class=example>
<pre class=language-css>
(orientation: landscape)
</pre>
</div>
<h3 id=min-width>Width</h3>
<pre class="descdef mq">
Name: width
Value: <<dimension>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="width" for=@element>min-width</a> responsive condition applies to any scoped element that has greater or equal (<code>>=</code>) width to the specified value.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="width" for=@element>min-width</a> element query
<pre class=language-css>
@element .widget and (min-width: 200px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that is at least <code>200px</code> or wider will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="width" for=@element>max-width</a> responsive condition applies to any scoped element that has lesser or equal (<code><=</code>) width to the specified value.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="width" for=@element>max-width</a> element query
<pre class=language-css>
@element .widget and (max-width: 200) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that <code>200px</code> or narrower will have a green background.
</div>
<h3 id=height>Height</h3>
<pre class="descdef mq">
Name: height
Value: <<dimension>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="height" for=@element>min-height</a> responsive condition applies to any scoped element that has greater or equal (<code>>=</code>) height to the specified value.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="height" for=@element>min-height</a> element query
<pre class=language-css>
@element .widget and (min-height: 50px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that is at least <code>50px</code> or taller will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="height" for=@element>max-height</a> responsive condition applies to any scoped element that has lesser or equal (<code><=</code>) height to the specified value.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="height" for=@element>max-height</a> element query
<pre class=language-css>
@element .widget and (max-height: 50px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that is at least <code>50px</code> or shorter will have a green background.
</div>
<h3 id=characters>Characters</h3>
<pre class="descdef mq">
Name: characters
Value: <<integer>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="characters" for=@element>min-characters</a> responsive condition applies to any scoped element that contains a greater or equal (<code>>=</code>) number of characters.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="characters" for=@element>min-characters</a> element query
<pre class=language-css>
@element input and (min-characters: 5) {
:self {
background: lime;
}
}
</pre>
In this case any input with 5 or more characters will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="characters" for=@element>max-characters</a> responsive condition applies to any scoped element that contains lesser or equal (<code><=</code>) number of characters specified.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="characters" for=@element>max-characters</a> element query
<pre class=language-css>
@element input and (max-characters: 5) {
:self {
background: lime;
}
}
</pre>
In this case any input with 5 or fewer characters will have a green background.
</div>
<h3 id=lines>Lines</h3>
<pre class="descdef mq">
Name: lines
Value: <<integer>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="lines" for=@element>min-lines</a> responsive condition applies to any scoped element that contains greater or equal (<code>>=</code>) number of specified lines of text.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="lines" for=@element>min-lines</a> element query
<pre class=language-css>
@element textarea and (min-lines: 3) {
:self {
background: lime;
}
}
</pre>
In this case any textarea with 3 or more lines will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="lines" for=@element>max-lines</a> responsive condition applies to any scoped element that contains lesser or equal (<code><=</code>) number of specified lines of text.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="lines" for=@element>max-lines</a> element query
<pre class=language-css>
@element textarea and (max-lines: 3) {
:self {
background: lime;
}
}
</pre>
In this case any textarea with 3 or fewer lines will have a green background.
</div>
<h3 id=children>Children</h3>
<pre class="descdef mq">
Name: children
Value: <<integer>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="children" for=@element>min-children</a> responsive condition applies to any scoped element that contains greater or equal (<code>>=</code>) number of child elements specified.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="children" for=@element>min-children</a> element query
<pre class=language-css>
@element .social-icons and (min-children: 5) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.social-icons</code> that contains more 5 or more direct descendants will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="children" for=@element>max-children</a> responsive condition applies to any scoped element that contains lesser or equal (<code><=</code>) number of child elements specified.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="children" for=@element>max-children</a> element query
<pre class=language-css>
@element .social-icons and (max-children: 5) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.social-icons</code> that contains more 5 or fewer direct descendants will have a green background.
</div>
<h3 id=scroll-y>Scroll-Y</h3>
<pre class="descdef mq">
Name: scroll-y
Value: <<dimension>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="scroll-y" for=@element>min-scroll-y</a> responsive condition applies to any scoped element that has scrolled a greater or equal (<code>>=</code>) amount to the value specified in a vertical direction.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="scroll-y" for=@element>min-scroll-y</a> element query
<pre class=language-css>
@element .feed and (min-scroll-y: 100px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.feed</code> that has scrolled <code>100px</code> or more vertical will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="scroll-y" for=@element>max-scroll-y</a> responsive condition applies to any scoped element that has scrolled a lesser or equal (<code><=</code>) amount to the value specified in a vertical direction.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="scroll-y" for=@element>max-scroll-y</a> element query
<pre class=language-css>
@element .feed and (max-scroll-y: 100px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.feed</code> that has scrolled <code>100px</code> or less vertically will have a green background.
</div>
<h3 id=scroll-x>Scroll-X</h3>
<pre class="descdef mq">
Name: scroll-x
Value: <<dimension>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="scroll-x" for=@element>min-scroll-x</a> responsive condition applies to any scoped element that has scrolled a greater or equal (<code>>=</code>) amount to the value specified in a horizontal direction.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="scroll-x" for=@element>min-scroll-x</a> element query
<pre class=language-css>
@element .feed and (min-scroll-x: 100px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.feed</code> that has scrolled <code>100px</code> or more horizontally will have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="scroll-x" for=@element>max-scroll-x</a> responsive condition applies to any scoped element that has scrolled a lesser or equal (<code><=</code>) amount to the value specified in a horizontal direction.
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="scroll-x" for=@element>max-scroll-x</a> element query
<pre class=language-css>
@element .feed and (max-scroll-x: 100px) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.feed</code> that has scrolled <code>100px</code> or less horizontally will have a green background.
</div>
<h3 id=aspect-ratio>Aspect-Ratio</h3>
<pre class="descdef mq">
Name: aspect-ratio
Value: <<ratio>>
For: @element
Type: range
</pre>
The <a class="property" data-link-type="propdesc" data-lt="aspect-ratio" for=@element>min-aspect-ratio</a> responsive condition applies to any scoped element with a greater or equal (<code>>=</code>) aspect ratio, specified as a <code>width</code> and <code>height</code> pair, separated by a slash (<code>/</code>).
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="aspect-ratio" for=@element>min-aspect-ratio</a> element query
<pre class=language-css>
@element .widget and (min-aspect-ratio: 16/9) {
:self {
background: lime;
}
}
</pre>
In this case any element that had an aspect ratio of <code>16/9</code> or greater would have a green background.
</div>
The <a class="property" data-link-type="propdesc" data-lt="aspect-ratio" for=@element>max-aspect-ratio</a> responsive condition applies to any scoped element with a lesser or equal (<code><=</code>) aspect ratio, specified as a <code>width</code> and <code>height</code> pair, separated by a slash (<code>/</code>).
<div class=example>
Example <a class="property" data-link-type="propdesc" data-lt="aspect-ratio" for=@element>max-aspect-ratio</a> element query
<pre class=language-css>
@element .widget and (max-aspect-ratio: 16/9) {
:self {
background: lime;
}
}
</pre>
In this case any element that had an aspect ratio of <code>16/9</code> or lesser would have a green background.
</div>
<h3 id=orientation>Orientation</h3>
<pre class="descdef mq">
Name: orientation
Value: portrait | square | landscape
For: @element
Type: discrete
</pre>
The 'orientation' responsive condition applies to any scoped element that matches the orientation specified. The following orientations are included: ''landscape'', <a class="css" data-link-type="maybe" data-lt="square" for=@element/orientation>square</a>, ''portrait''
<h4 id=portrait-orientation>Portrait Orientation</h4>
<dl dfn-type=value dfn-for=@element/orientation>
<dt><dfn>portrait</dfn>
<dd>The 'orientation' is ''portrait'' if the scoped element has a greater (<code>></code>) height than width
</dl>
<div class=example>
Element query for ''portrait'' orientation</strong>
<pre class=language-css>
@element .widget and (orientation: portrait) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that is narrower than it is tall will have a green background.
</div>
<h4 id=square-orientation>Square Orientation</h4>
<dl dfn-type=value dfn-for=@element/orientation>
<dt><dfn>square</dfn>
<dd>The 'orientation' is <a class="css" data-link-type="maybe" data-lt="square" for=@element/orientation>square</a> if the scoped element has an equal (<code>=</code>) height and width
</dl>
<div class=example>
Element query for <a class="css" data-link-type="maybe" data-lt="square" for=@element/orientation>square</a> orientation</strong>
<pre class=language-css>
@element .widget and (orientation: square) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that has an equal width and height will have a green background.
</div>
<h4 id=landscape-orientation>Landscape Orientation</h4>
<dl dfn-type=value dfn-for=@element/orientation>
<dt><dfn>landscape</dfn>
<dd>The 'orientation' is ''landscape'' if the scoped element has a greater (<code>></code>) width than height
</dl>
<div class=example>
Element query for ''landscape'' orientation</strong>
<pre class=language-css>
@element .widget and (orientation: landscape) {
:self {
background: lime;
}
}
</pre>
In this case any element with a class of <code>.widget</code> that is wider than it is tall will have a green background.
</div>
<h2 id=element-percentage-units>Element-percentage Units</h2>
Just as CSS has viewport-percentage units: ''vw'', ''vh'', ''vmin'', and ''vmax'' which represent a distance equal to 1% of the viewport width, height, shortest edge, and longest edge, in a similar way the following element-percentage units ''ew'', ''eh'', ''emin'', and ''emax'' represent a distance equal to 1% of the element's own width, height, shortest edge, and longest edge. When the width of height of the element changes, the value of these units scale accordingly.
Note: These new <a dfn>eq-unit</a> units always refer to the dimensions of the element in the scope, and can be used inside of a scoped stylesheet to style other elements.
<dl dfn-type=value dfn-for=eq-unit>
<dt><dfn id=ew lt=ew>ew unit</dfn>
<dd>
Equal to 1% of the width of the scoped element
<div class=example>
Example of ew Units Inside a Scoped Style
<pre class=language-css>
@element .widget {
:self {
font-size: 10ew;
}
}
</pre>
In this case the font size of any element with a class of <code>.widget</code> is equal to 10% of the scoped element's width.
</div>
Note: This unit is similar to the ''vw'' viewport unit, but based on the scoped element's dimensions.
<dt><dfn id=eh lt=eh>eh unit</dfn>
<dd>
Equal to 1% of the height of the scoped element
<div class=example>
Example of eh Units Inside a Scoped Style
<pre class=language-css>
@element .widget {
:self {
font-size: 10eh;
}
}
</pre>
In this case the font size of any element with a class of <code>.widget</code> is equal to 10% of the scoped element's height.
</div>
Note: This unit is similar to the ''vh'' viewport unit, but based on the scoped element's dimensions.
<dt><dfn id=emin lt=emin>emin unit</dfn>
<dd>
Equal to the smaller of 1ew or 1eh
<div class=example>
Example of emin Units Inside a Scoped Style
<pre class=language-css>
@element .widget {
:self {
font-size: 10emin;
}
}
</pre>
In this case the font size of any element with a class of <code>.widget</code> is equal to 10% of the scoped element's shortest edge.
</div>
Note: This unit is similar to the ''vmin'' viewport unit, but based on the scoped element's dimensions.
<dt><dfn id=emax lt=emax>emax unit</dfn>
<dd>
Equal to the larger of 1ew or 1eh
<div class=example>
Example of emax Units Inside a Scoped Style
<pre class=language-css>
@element .widget {
:self {
font-size: 10emax;
}
}
</pre>
In this case the font size of any element with a class of <code>.widget</code> is equal to 10% of the scoped element's longest edge.
</div>
Note: This unit is similar to the ''vmax'' viewport unit, but based on the scoped element's dimensions.
</dl>
<h2 id=examples-of-element-queries>Examples of Scoped Styles & Element Queries</h2>
<h3 id=example-scoped-styles>Examples of valid scoped stylesheets</h3>
<div class=example>
<pre class=language-css>
@element div {}
</pre>
</div>
<div class=example>
<pre class=language-css>
@element div, span {}
</pre>
</div>
<div class=example>
<pre class=language-css>
@element div and (min-width: 500px) {}
</pre>
</div>
<div class=example>
<pre class=language-css>
@element div and (min-width: 500px) and (min-lines: 3) {}
</pre>
</div>
<h3 id=faking-input-empty>Faking <code>input:empty</code></h3>
<div class=example>
<pre class=language-html>
<input>
<style>
/* input:empty */
@element input and (max-characters: 0) {
:self {
background: red;
}
}
/* input:not(:empty) */
@element input and (min-characters: 1) {
:self {
background: lime;
}
}
</style>
</pre>
In this example we are able to apply styles based on whether there are zero or at least one characters inside any <code>input</code> element. CSS has the pseudo-class '':empty'', however it doesn't apply to all elements (like <code>input</code> elements) so by using <code>max-characters</code> and <code>min-characters</code> with element queries we are able to express and style a similar idea.
</div>
<h3 id=self-responsive-grid>Self-responsive Grid</h3>
<div class=example>
<pre class=language-html>
<h2>Responsive Grid</h2>
<p>Small = full width, Medium = thirds, Large = sixths.</p>
<section data-grid>
<div class="col-10 medium-split-3 large-split-6"></div>
<div class="col-10 medium-split-3 large-split-6"></div>
<div class="col-10 medium-split-3 large-split-6"></div>
<div class="col-10 medium-split-3 large-split-6"></div>
<div class="col-10 medium-split-3 large-split-6"></div>
<div class="col-10 medium-split-3 large-split-6"></div>
</section>
<h2>Split Grid</h2>
<p>Small = half width, Medium = 1, 2, 3, 4 split, Large = 4, 3, 2, 1 split.</p>
<section data-grid>
<div class="col-5 medium-split-1 large-split-4"></div>
<div class="col-5 medium-split-2 large-split-4"></div>
<div class="col-5 medium-split-2 large-split-4"></div>
<div class="col-5 medium-split-3 large-split-4"></div>
<div class="col-5 medium-split-3 large-split-3"></div>
<div class="col-5 medium-split-3 large-split-3"></div>
<div class="col-5 medium-split-4 large-split-3"></div>
<div class="col-5 medium-split-4 large-split-2"></div>
<div class="col-5 medium-split-4 large-split-2"></div>
<div class="col-5 medium-split-4 large-split-1"></div>
</section>
<h2>Hidden Elements</h2>
<p>Small = Hide Small, Medium = Hide Medium, Large = Hide Large.</p>
<section data-grid>
<div class="col-10 hide-small">Small</div>
<div class="col-10 hide-medium">Medium</div>
<div class="col-10 hide-large">Large</div>
</section>
<style>
* {
box-sizing: border-box;
}
[data-grid] div {
min-height: 50px;
background: lime;
border: 5px solid white;
}
/* Element Query Grid */
@element [data-grid] {
:self,
:self * {
box-sizing: border-box;
}
:self:after,
:self [data-row]:after {