-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspecification.html
1484 lines (1402 loc) · 90.2 KB
/
specification.html
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
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8" />
<!--***************************************************************
AUTHORS: Miro Keller and collaborators
COPYRIGHT: (c)2013 - All Rights Reserved
LICENSE: see License.txt file
WEB: http://axrproject.org
THIS CODE AND INFORMATION ARE PROVIDED "AS IS"
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR
FITNESS FOR A PARTICULAR PURPOSE.
*******************************************************************
FILE INFORMATION:
=================
Last changed: 2013/10/17
HSS version: 1.0
Revision: 1.6
****************************************************************-->
<title>The AXR Specification</title>
<meta name="author" content="Miro Keller, Marc G." />
<style type="text/css">
body
{
width: 720px;
font-family: "Century Gothic", "Futura", "Verdana", sans-serif;
margin: 30px auto;
color: #666;
}
a[href^="#"], :local-link
{
-moz-text-decoration-line:underline;
-moz-text-underline-style:dotted;
-webkit-text-decoration-line:underline;
-webkit-text-decoration-style:dotted;
}
.notice
{
margin: 20px auto;
background-color: rgba(153,153,153,0.1);
padding: 20px;
border-radius: 15px
}
.notice p
{
margin: 5px 0;
}
.notice strong
{
color: red;
}
p.center, h1
{
text-align: center;
}
p > span
{
background: #fef3c8;
padding: 0 2px;
border: 1px solid #dca992;
color: #b5471a;
border-radius: 2px;
font-family: monospace;
}
code, pre
{
background: #FEF3C8;
padding: 20px;
border: 1px solid #DCA992;
color: #B5471A;
border-radius: 2px;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word;
}
p code, ul code
{
padding: 0 2px;
}
section ul
{
list-style: circle outside;
}
.comment
{
color: #95877e;
}
.selector
{
color: #fd2f7a;
}
.property
{
color: #1b8a93;
}
.filter
{
color: #199013;
}
.combinator
{
color: #1e97f4;
}
.object
{
color: #933492;
}
.number
{
color: #2146fa;
}
.string
{
color: #fd2716;
}
.modifier
{
color: #000;
}
.instruction
{
color: #8A0067;
}
.flag
{
color: #8D8711;
}
.splitter
{
color: #E52A90;
}
pre .highlighted
{
background-color: #fefefe;
}
table
{
width: 100%;
border: 1px solid #CCC;
}
table th
{
background-color: #CCC;
padding: 10px;
}
table th:first-child
{
}
table td
{
border: 1px solid #CCC;
text-align: left;
padding: 10px;
}
pre.xml
{
background-color: #d6fcd0;
border-color: #5bac80;
color: #498e68;
}
ul, #spec ol
{
list-style: inside;
line-height: 1.4;
margin: 10px;
}
ul li, ol li
{
color: #666666;
}
nav li
{
list-style:none;
font-size:13px;
line-height:18px;
}
nav li li
{
font-size:11px;
line-height:15px;
}
nav > ul
{
counter-reset:section;
background-color:#f5f7f6;
margin:0 auto;
padding:20px;
-moz-column-count: 2;
-moz-column-gap: 1em;
-webkit-column-count: 2;
-webkit-column-gap: 1em;
column-count: 2;
column-gap: 1em;
height: 610px;
}
nav > ul > li
{
counter-reset:subsection;
}
nav > ul > li:before
{
counter-increment:section;
content:"1." counter(section) " ";
}
nav > ul > li > ul > li:before
{
counter-increment:subsection;
content:"1." counter(section) "." counter(subsection) " ";
}
nav li.hasSub ul
{
display:none;
}
nav li.hasSub:hover ul
{
display:block;
}
nav li.hasSub li
{
counter-increment:alpha;
}
nav li.hasSub li:before
{
counter-increment:none;
content:"1." counter(section) "." counter(subsection) "." counter(alpha, upper-latin) " ";
}
.sub.yet:hover h4:after, .sub.part:hover h4:after, .sub.comp:hover h4:after
{
content:" [not supported yet]";
font-weight:normal;
font-size:xx-small;
vertical-align:text-top;
}
.sub.part:hover h4:after
{
content:" [partially supported]"
}
.sub.comp:hover h4:after
{
content:" [supported]"
}
.sub.yet
{
filter: alpha(opacity=50);
-moz-opacity: 0.5;
-khtml-opacity: 0.5;
opacity: 0.5;
}
.sub.yet:hover
{
filter: alpha(opacity=100);
-moz-opacity: 1;
-khtml-opacity: 1;
opacity: 1;
}
h5:before
{
content: "\2042\00A0";
font-size:14px;
}
.subsec
{
color: #8e4dd0;
}
.subsec:before
{
content: "\00A7\00A0";
font-size: 22px;
font-weight: normal;
}
.subsec:after
{
display:none;
}
h4 span.number:hover:before, h3 span.number:hover:before
{
content:"\2735";
font-size:32px;
font-weight:normal;
position:absolute;
margin:-10px 0 0 -30px;
}
#btt
{
position:fixed;
bottom:5px;
right:5px;
font-size:xx-small;
}
em.monospace
{
font-family: monospace;
font-style: normal;
}
.compound-word
{
background: none;
border: 0;
color: #666;
font-family: "Century Gothic", "Futura", "Verdana", sans-serif;
padding: 0;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="draft_warning" class="notice">
<p><strong>Warning!</strong></p>
<p>This file is an editor's draft and should not be considered final.</p>
</div>
<h1>Arbitrary XML Rendering Specification</h1>
<nav><a id="toc"></a>
<ul>
<li><a href="#n1.1">Introduction</a></li>
<li><a href="#n1.2">The primary building blocks</a>
<ul>
<li><a href="#n1.2.1">Rules</a></li>
<li><a href="#n1.2.2">Selector basic principles</a></li>
<li><a href="#n1.2.3">Properties</a></li>
<li><a href="#n1.2.4">Objects</a></li>
<li><a href="#n1.2.5">HSS points</a></li>
<li><a href="#n1.2.6">The negator</a></li>
</ul>
</li>
<li><a href="#n1.3">Selectors</a>
<ul>
<li><a href="#n1.3.1">Element name</a></li>
<li><a href="#n1.3.2">Hierarchy & Scope</a></li>
<li><a href="#n1.3.3">Grouping</a></li>
<li><a href="#n1.3.4">The universal selector</a></li>
<li><a href="#n1.3.5">Selecting the subject</a></li>
<li><a href="#n1.3.6">Regex selector</a></li>
<li><a href="#n1.3.7">Reference objects</a></li>
</ul>
</li>
<li><a href="#n1.4">Combinators</a>
<ul>
<li><a href="#n1.4.1">Child combinator</a></li>
<li><a href="#n1.4.2">Descendant combinator</a></li>
<li><a href="#n1.4.3">Siblings combinator</a></li>
<li><a href="#n1.4.4">Next and previous siblings combinators</a></li>
<li><a href="#n1.4.5">Accessing elements laid out in lines</a></li>
<li><a href="#n1.4.6">Content text combinator</a></li>
<li><a href="#n1.4.7">Ancestor combinator</a></li>
</ul>
</li>
<li><a href="#n1.5">Filters, flags and splitters</a>
<ul>
<li><a href="#n1.5.1">Position filters</a></li>
<li><a href="#n1.5.2">Hierarchy filters</a></li>
<li><a href="#n1.5.3">System flags</a></li>
<li><a href="#n1.5.4">The attribute filter</a></li>
<li><a href="#n1.5.5">Text matching filters</a></li>
<li><a href="#n1.5.6">The property filter</a></li>
<li><a href="#n1.5.7">Splitters</a></li>
<li><a href="#n1.5.8">Collection filters</a></li>
<li><a href="#n1.5.9">Custom macros</a></li>
<li><a href="#n1.5.10">User flags</a></li>
</ul>
</li>
<li><a href="#n1.6">Properties</a>
<ul>
<li><a href="#n1.6.1">Literal values</a></li>
<li><a href="#n1.6.2">Expressions</a></li>
<li class="hasSub"><a href="#n1.6.3">Functions</a>
<ul>
<li><a href="#n1.6.3.a">Retrieval functions</a></li>
<li><a href="#n1.6.3.b">Type functions</a></li>
<li><a href="#n1.6.3.c">Arithmetic functions</a></li>
</ul>
</li>
<li><a href="#n1.6.4">Color</a></li>
<li><a href="#n1.6.5">Grouping</a></li>
<li><a href="#n1.6.6">The value selector</a></li>
<li><a href="#n1.6.7">Boolean casting</a></li>
<li><a href="#n1.6.8">Concatenation</a></li>
<li><a href="#n1.6.9">Custom properties</a></li>
</ul>
</li>
<li><a href="#n1.7">Objects</a>
<ul>
<li><a href="#n1.7.1">Object dot notation</a></li>
<li><a href="#n1.7.2">Named objects</a></li>
<li><a href="#n1.7.3">Anonymous objects</a></li>
<li><a href="#n1.7.4">Shorthand notation</a></li>
<li><a href="#n1.7.5">Grouping and inheritance</a></li>
</ul>
</li>
<li><a href="#n1.8">Instructions</a>
<ul>
<li><a href="#n1.8.1">Import</a></li>
<li><a href="#n1.8.2">Support</a></li>
<li><a href="#n1.8.3">Wrap</a></li>
<li><a href="#n1.8.4">Move</a></li>
<li><a href="#n1.8.5">New</a></li>
</ul>
</li>
</ul>
</nav>
<div id="hss_syntax">
<h2><span>1</span> The syntax of HSS</h2>
<section class="chapter">
<h3><span class="number"><a href="#n1.1" id="n1.1">1.1</a></span> Introduction</h3>
<p>HSS stands for Hierarchical Style Sheets and it is the language used to instruct the AXR renderer how the various elements in the document should look like, how they are laid out and, to some extent, how they behave. The syntax of this language is inspired by CSS, but extending and altering it in various ways, to achieve powerful new ways of creating a web document. Therefore, HSS is not compatible with existing CSS files.</p>
<p>HSS inherits the simplicity and clarity of CSS' syntax, but stops being a static language, bearing more similarity in some areas to other programming languages. The primary premise for this is the realization that a web page isn't a simple hyperlinked text document anymore, but an interactive software, which presents itself to the user through an interface and performs some logic, which may or not be displaying a text document. With this in mind, and the environment in which the document will be accessed (a computing device with an arbitrary display size), it is clear that some sort of interface programming language is needed which is able to express relationships and behaviors, and allows advanced interactivity and layout.</p><p>HSS files are plain-text files, and thus can be edited by any text editor on any platform, although some of its features are better put to use through a visual editing tool, since using code in those cases is less intuitive.</p>
</section>
<section class="chapter">
<h3><span class="number"><a href="#n1.2" id="n1.2">1.2</a></span> The primary building blocks</h3>
<h4><span class="number"><a href="#n1.2.1" id="n1.2.1">1.2.1</a></span> Rules</h4>
<p>One of the most basic concepts in HSS is the notion of rules. A rule is the combination of a selector and a block, which starts with an opening curly brace <code>{</code> and ends with a closing one <code>}</code>, and may contain property definitions and/or other rules.</p>
<pre><span class="selector">selector</span>
{
<span class="property">property</span>: value;
<span class="selector">selector</span> { … }
}</pre>
<h4><span class="number"><a href="#n1.2.2" id="n1.2.2">1.2.2</a></span> Selector basic principles</h4>
<p><a href="#n1.3">Selectors</a> are used to point to certain elements of the document, so that the properties defined inside of the block get applied to them. You define a search pattern and all applicable elements will be searched to see if the conditions match. If so, the property definitions are applied.</p>
<p>Simple selectors are the <a href="#n1.3.1">element names</a>, the <a href="#n1.3.4">universal selector</a> and <a href="#n1.3.7">reference objects</a>, combined with one or several appended <a href="#n1.5">filters, flags or splitters</a>. A series of simple selectors joined by <a href="#n1.4">combinators</a> is called the selector (or selector chain) and reads from left to right.</p>
<p>Some examples:</p>
<pre><span class="comment">//select elements with name "document"</span>
<span class="selector">document</span> { }
<span class="comment">//select the first element with name "book"</span>
<span class="selector">book</span><span class="filter">:first</span> { }
<span class="comment">//select the elements with name "content" that occur after "title"
//elements, which are descendants of "book" elements, which themselves
//are direct children of "books" elements</span>
<span class="selector">books book</span> <span class="combinator">..</span> <span class="selector">title</span> <span class="combinator">+</span><span class="combinator"></span> <span class="selector">content</span> { }</pre>
<h4><span class="number"><a href="#n1.2.3" id="n1.2.3">1.2.3</a></span> Properties</h4>
<p>Each element in the document has a certain amount of <a href="#n1.6">properties</a>, which you can define using property definitions. They are contained within the block that follows a selector chain.</p>
<p>A property declaration is composed of the name of the property followed by optional whitespace, a colon, and finally, preceded by optional whitespace, comes either a literal value, an expression, a function or an object. More whitespace can come afterwards, as well. If it is not the last property declaration of the block, it must be ended by a semicolon, to denote that it finishes on that place, and that what follows is something else.</p>
<p>Here are some examples:</p>
<pre><span class="selector">document</span>
{
<span class="comment">//this makes it 150 <a href="#n1.2.5">points</a> wide</span>
<span class="property">width</span>: <span class="number">150</span>;
<span class="comment">//this makes the element 10 points less high than its parent's <a href="http://hss.axrproject.org/@container#innerHeight">innerHeight</a></span>
<span class="property">height</span>: <span class="number">100%</span> - <span class="number">10</span>;
<span class="comment">//this aligns the element to the center of its parent element</span>
<span class="property">alignX</span>: <span class="number">50%</span>;
<span class="property">alignY</span>: <span class="number">50%</span>;
}
<span class="comment">//in this example the semicolon was omitted, since that
//property immediately precedes the closing brace</span>
<span class="selector">document</span> { <span class="property">alignX</span>: <span class="number">50%</span> }</pre>
<h4><span class="number"><a href="#n1.2.4" id="n1.2.4">1.2.4</a></span> Objects</h4>
<p><a href="#n1.7">Objects</a> represent values that are more complex in their nature. Similar to rules, objects have properties which accept values, defined inside a block. Objects are identified using the object sign <code>@</code> prefixed to their object type.</p>
<pre><span class="selector">document</span>
{
<span class="comment">//this makes the element have rounded corners</span>
<span class="property">shape</span>: <span class="object">@roundedRect</span> {
<span class="property">corners</span>: <span class="number">5</span>;
};
<span class="comment">//this adds a 3 points wide black border</span>
<span class="property">border</span>: <span class="object">@stroke</span> {
<span class="property">size</span>: <span class="number">3</span>;
<span class="property">color</span>: <span class="number">#000</span>;
};
}</pre>
<h4><span class="number"><a href="#n1.2.5" id="n1.2.5">1.2.5</a></span> HSS points</h4>
#TODO <a href="https://github.com/AXR/Specification/issues/68">Issue 68</a>
<div class="sub part">
<h4><span class="number"><a href="#n1.2.6" id="n1.2.6">1.2.6</a></span> The negator</h4>
<p>You can negate simple selectors by prefixing them with <code>!</code>, meaning that all elements in the current scope that don't match the selector will be selected.</p>
<pre><span class="comment">//this selects all elements except note ones</span>
<span class="modifier">!</span><span class="selector">note</span> { }</pre>
<p>Likewise you can negate filters and flags.</p>
<pre><span class="comment">//this selects any note element which is not the first one</span>
<span class="selector">note</span><span class="modifier">!</span><span class="filter">:first</span> { }
<span class="comment">//this selects any note element which is not being hovered</span>
<span class="selector">note</span><span class="modifier">!</span><span class="flag">::hover</span> { }</pre>
<p>To negate an entire selector (taking into account its filters and flags) you have to use <a href="#square">grouping brackets</a>.</p>
<pre><span class="comment">//this matches all elements except the last note(s)</span>
<span class="modifier">!</span>[<span class="selector">note</span><span class="filter">:last</span>] {}</pre>
<p>The negator can also be prepended to values.</p>
<pre><span class="selector">note</span>
{
<span class="comment">//using a <a href="#n1.6.3.1">reference</a>, this ensures that the element
//is not <a href="http://hss.axrproject.org/@container#targetable">targetable</a> when it is <a href="http://hss.axrproject.org/@container#draggable">draggable</a>
//and targetable when it's not draggable</span>
<span class="property">targetable</span>: <span class="modifier">!</span>ref(<span class="property">draggable</span>);
}</pre>
</div>
</section>
<section class="chapter">
<h3><span class="number"><a href="#n1.3" id="n1.3">1.3</a></span> Selectors</h3>
<p>Consider the following XML snippet:</p>
<pre class="xml"><<span class="selector">note</span>>
<<span class="selector">to</span>>Peter</<span class="selector">to</span>>
<<span class="selector">from</span>>James</<span class="selector">from</span>>
<<span class="selector">subject</span>>Reminder</<span class="selector">subject</span>>
<<span class="selector">message</span>>Please don't forget to bring some <<span class="selector">important</span>>wine</<span class="selector">important</span>>…</<span class="selector">message</span>>
</<span class="selector">note</span>></pre>
<p>In the following examples we will be using rules, but without property definitions for clarity. We will assume that this xml snippet could be inserted anywhere: the <em>note</em> element doesn't necessarily represent the root of the xml document.</p>
<div class="sub comp">
<h4><span class="number"><a href="#n1.3.1" id="n1.3.1">1.3.1</a></span> Element name</h4>
<p>You can target an element by its tag name.</p>
<pre><span class="comment">//match every note element (within the current scope) and apply
//the style rules declared within the block (in this case none)</span>
<span class="selector">note</span> { }</pre>
</div>
<div class="sub comp">
<h4><span class="number"><a href="#n1.3.2" id="n1.3.2">1.3.2</a></span> Hierarchy & Scope</h4>
<p>Usually what the HSS author does is following the document tree and applying styles to most elements. Rules can be nested inside other rules which will only match children of the elements matched by the parent selector. This is what gives HSS its name.</p>
<p>The scope refers to the elements targeted by the selector. In the following example, only message elements that are immediate children of note can be selected, because the scope is restricted to the children of the note element.</p>
<pre><span class="selector">note</span>
{
<span class="comment">//match every message element which is a child
//of the previously selected note element</span>
<span class="selector">message</span> { }
}</pre>
<p>Similarly to avoid repetition you can nest the <a href="#n1.3.7.1">this object</a> affixed with filters or flags.</p>
<pre><span class="selector">note</span><br />{
<span class="object">@</span><span class="flag">::hover</span> { }
}
<span class="comment">//which is equivalent to</span>
<span class="selector">note</span><br />{
<span class="object">@this</span><span class="flag">::hover</span> { }
}
<span class="comment">//which is equivalent to</span>
<span class="selector">note</span> { }
<span class="selector">note</span><span class="flag">::hover</span> { }</pre>
</div>
<div class="sub part">
<h4><span class="number"><a href="#n1.3.3" id="n1.3.3">1.3.3</a></span> Grouping</h4>
<p>You can group multiple selectors together which is convenient when they share the same properties (or rules).</p>
<pre><span class="comment">//match the note's children of type subject and message</span>
<span class="selector">note</span> <span class="selector">subject</span>, <span class="selector">note</span> <span class="selector">message</span> { }</pre>
<p>Selector grouping helps getting rid of unnecessary repetition.</p>
<pre>
<span class="comment">//hierarchical grouping</span>
note {
child1, child2 {
element1, element2 { }
}
}
<span class="comment">//which is equivalent to</span>
note { }
note child1, note child2 { }
note child1 element1, note child1 element2,
note child2 element1, note child2 element2 { }</pre>
<p>Through the use of <a id="square">grouping brackets</a>, several consecutive parts of a selector chain can be evaluated as one.</p>
<pre><span class="comment">//inline grouping is also available</span>
note [child1, child2] [element1, element2] { }
<span class="comment">//which is equivalent to</span>
note child1 element1, note child1 element2,
note child2 element1, note child2 element2 { }
<span class="comment">//this could match B elements which precede A elements
//(which themselves are followed by C elements)</span>
[A + C] - B { }
<span class="comment">//which is equivalent to</span>
A + C - B { }
<span class="comment">//this couldn't: the B elements would have to come after an A
//and before a C</span>
A + [C - B] { }</pre>
<p>You can also apply filters, flags or splitters to the aggregate resulting from the combined collections.</p>
<pre><span class="comment">//matches the odd element(s) of the collection of A1 and A2 elements</span>
[A1, A2]:odd { }
<span class="comment">//which is not equivalent to</span>
A1:odd, A2:odd { }</pre>
<p>Grouping brackets can also be used to join collections of a simple selector.</p>
<pre><span class="comment">//this would join the collections of odd elements of each type
//and then out of that match the odd ones</span>
[<span class="selector">*</span><span class="splitter">/type</span><span class="filter">:odd</span>]<span class="filter">:odd</span> { }</pre>
</div>
<div class="sub comp">
<h4><span class="number"><a href="#n1.3.4" id="n1.3.4">1.3.4</a></span> The universal selector</h4>
<p>The universal selector <span class="selector">*</span> matches every element in the current scope:</p>
<pre><span class="comment">//matches every element that is a child of <em>note</em></span>
<span class="selector">note</span>
{
<span class="selector">*</span> { }
}</pre>
<p><em>Reminder:</em> Since the initial scope is restricted to the root element, simply using the universal selector in the outermost rule set would only select one element, unlike what would happen in CSS. To traverse all scopes you need to start the selector chain with the <a href="#n1.4.2">descendant combinator</a>.</p>
<pre><span class="comment">//matches only the root element</span>
<span class="selector">*</span> { }
<span class="comment">//matches all elements under the root element</span>
<span class="selector">*</span> <span class="combinator">..</span> <span class="selector">*</span> { }
<span class="comment">//matches all elements</span>
<span class="combinator">..</span> <span class="selector">*</span> { }</pre>
<p>If the universal selector is not the only part of the selector, like when it has a filter, for example, it can be omitted. It may be omitted as well if placed between matching combinators (except the child and descendant combinators).</p>
<pre><span class="comment">//the following statements are equivalent</span>
<span class="selector">*</span><span class="filter">:first</span> { }
<span class="filter">:first</span> { }
<span class="comment">//and so are these</span>
<span class="selector">*</span> <span class="combinator">></span> <span class="selector">*</span> <span class="combinator">></span> <span class="selector">*</span> { }
<span class="selector">*</span> <span class="combinator">>></span> <span class="selector">*</span> { }</pre>
</div>
<div class="sub yet">
<h4><span class="number"><a href="#n1.3.5" id="n1.3.5">1.3.5</a></span> Selecting the subject</h4>
<p>Using the subject selector <code>$</code> you can match an element anywhere in the selector chain thus turning everything that follows it into a condition.</p>
<pre><span class="comment">//matches all note elements which have at least one comment element as a child</span>
<span class="modifier">$</span><span class="selector">note</span><span class="combinator"> </span><span class="selector">comment</span> { }
<span class="comment">//matches the note element which has an <em>important</em>
//descendant currently being hovered</span>
<span class="modifier">$</span><span class="selector">note</span> <span class="combinator">..</span> <span class="selector">important</span><span class="flag">::hover</span> { }</pre>
</div>
<div class="sub yet">
<h4><span class="number"><a href="#n1.3.6" id="n1.3.6">1.3.6</a></span> Regex selector</h4>
<p>You can use a regular expression to select elements based on their names.</p>
<pre><span class="comment">//matches every element in the current scope whose name starts with <em>a</em></span>
<span class="selector">/^a/</span> { }
<span class="comment">//matches every element in the current scope whose name starts with <em>a</em> or <em>A</em>
//i stands for insensitive</span>
<span class="selector">/^a/i</span> { }
<span class="comment">//matches every element in the current scope whose name starts with <em>fi</em> or <em>fi</em>
//l stands for ligature</span>
<span class="selector">/^fi/l</span> { }
<span class="comment">//matches every element in the current scope whose name starts with <em>a</em>, <em>à</em>, <em>â</em>, etc.
//d stands for diacritic</span>
<span class="selector">/^a/d</span> { }</pre>
</div>
<div class="sub part">
<h4 class="title"><span class="number"><a href="#n1.3.7" id="n1.3.7">1.3.7</a></span> Reference Objects</h4>
<p>The <a href="#n1.3.7.1" id="n1.3.7.1"><strong>this object</strong></a> always refers to the nearest container(s); independently of each other (if there are several matches). It can be used in a selector or a property's value.</p>
<pre><span class="comment">//using the <a href="#n1.7.1">object dot notation</a>, this would set the width
//to the element's <strong>current</strong> <em>computed</em> height value</span>
<span class="selector">element</span>
{
<span class="property">height</span>: 100%;
<span class="property">width</span>: <span class="object">@this</span>.<span class="property">height</span>;
}</pre>
<p>The <a href="#n1.3.7.2" id="n1.3.7.2"><strong>self object</strong></a> refers to the current object which immediately contains it. It is especially useful when it targets <a href="#n1.7.3">anonymous objects</a>.</p>
<pre><span class="comment">//sets the file name as the window's title</span>
<span class="object">@window</span>
{
<span class="property">title</span>: <span class="object">@self</span>.<span class="property">file</span>;
}</pre>
<p>The <a href="#n1.3.7.3" id="n1.3.7.3"><strong>root object</strong></a> refers to the topmost element (<abbr title="also known as">AKA</abbr> document element), the one that encloses all others in the document.</p>
<pre><span class="comment">//this sets the width of the <em>section</em> element(s)
//to the same value as the width of the root element
//if it is named "document" (using the <a href="#f_is">is filter</a>)</span>
<span class="combinator">..</span> <span class="selector">section</span>
{
<span class="property">width</span>: ref(<span class="property">width</span> of <span class="object">@root</span><span class="filter">:is(document)</span>);
}</pre>
<p><em>Note:</em> You can turn a generic element into a root element <em>towards its descendants</em> using the <a href="http://hss.axrproject.org/@container#sandbox">sandbox property</a>.</p>
<p>The <a href="#n1.3.7.4" id="n1.3.7.4"><strong>parent object</strong></a> refers to the parent of the preceding element in the selector chain or (if there's none before) to the parent of the element which is currently affected by the styling rule containing <span class="object">@parent</span>.</p>
<pre><span class="comment">//set the messages' width to a third of their own parents' height</span>
<span class="combinator">..</span> <span class="selector">message</span>
{
<span class="property">width</span>: ref(<span class="property">height</span> of <span class="object">@parent</span>) / <span class="number">3</span>;
}
<span class="comment">//this reference would return nothing since
//the headmost root element is devoid of any ancestor</span>
<span class="object">@root</span>
{
<span class="property">height</span>: ref(<span class="property">height</span> of <span class="object">@parent</span>);
}
<span class="comment">//in case @parent starts the selector chain
//it relates to the current @this</span>
<span class="combinator">..</span> <span class="selector">message</span>
{
<span class="object">@parent</span> { }
<span class="comment">//resolves to</span>
<span class="object">@this</span> <span class="object">@parent</span> { }
}</pre>
<p>The <a href="#n1.3.7.5" id="n1.3.7.5"><strong>these object</strong></a> refers to the nearest container(s) as a whole. It is particularly useful in case the rightmost selector is unknown.</p>
<pre><span class="comment">//to be later used by the <a href="http://hss.axrproject.org/@container#isA">isA</a> property</span>
<span class="object">@container</span> loftiest
{
<span class="comment">//this sets the height of the elements matched
//to the height of whichever is currently the tallest</span>
<span class="property">height</span>: ref(<span class="modifier">max</span> <span class="property">height</span> of <span class="object">@these</span>);
}</pre>
<p>The <a href="#n1.3.7.6" id="n1.3.7.6"><strong>owner object</strong></a> refers to the object which immediately contains the current object. It's designed to retrieve values from varying or multiple owners.</p>
#TODO example
<p><em>Reminder:</em> elements are objects of type container.</p>
<p>The <a href="http://hss.axrproject.org/@window" id="n1.3.7.7"><strong>window object</strong></a> holds the properties pertaining to the window.</p>
<pre><span class="object">@window</span>
{
<span class="property">title</span>: <span class="string">"This is my custom title."</span>;
}</pre>
</div>
</section>
<section class="chapter">
<h3 class="title"><span class="number"><a href="#n1.4" id="n1.4">1.4</a></span> Combinators</h3>
<p>Combinators allow you to select an element based on its relationship to another in the hierarchy. Multiple simple selectors can be chained together, forming the selector chain. Usually this is done when you want to "skip" the elements which leads to the one you want to style. In the case of a single childhood relationship, it is more convenient to use the child combinator than to nest rules; in other cases, combinators are mandatory regardless.</p>
<pre><span class="comment">//even in a hierarchical context
//you can start a selector chain by a combinator</span>
<span class="selector">note</span>
{
<span class="comment">//this matches <em>important</em> elements which are descendants of <em>note</em> elements</span>
<span class="combinator">..</span> <span class="selector">important</span> { }
}
<span class="comment">//which is equivalent to</span>
<span class="selector">note</span> { }
<span class="selector">note</span> <span class="combinator">..</span> <span class="selector">important</span> { }</pre>
<p>Keep in mind that these examples only select elements in the current scope, and therefore will select elements depending on where in the hierarchy you are using them.</p>
<div class="sub comp">
<h4 class="title"><span class="number"><a href="#n1.4.1" id="n1.4.1">1.4.1</a></span> Child combinator</h4>
<p>Children—or more explicitly level one descendants—may be selected using the child combinator (whitespace) <span class="combinator"> </span>.</p>
<p><em>Note:</em> This is different from CSS, where the whitespace represents the descendant combinator. The reasoning behind this is that authors are inherently lazy, and thus end up using the descendant combinator when they really should be using the child combinator instead, because it's just much more convenient.</p>
<pre><span class="comment">//matches every subject element which is a child of note</span><br /><span class="selector">note subject</span> { }</pre>
</div>
<div class="sub comp">
<h4 class="title"><span class="number"><a href="#n1.4.2" id="n1.4.2">1.4.2</a></span> Descendant combinator</h4>
<p>If you want to select elements which are descendants (could be direct children of the element, or more generations down), the descendant combinator <span class="combinator">..</span> is used.</p>
<pre><span class="comment">//matches every subject element which is a descendant of note</span><br /><span class="selector">note</span> <span class="combinator">..</span> <span class="selector">subject</span> { }</pre>
</div>
<div class="sub comp">
<h4 class="title"><span class="number"><a href="#n1.4.3" id="n1.4.3">1.4.3</a></span> Siblings combinator</h4>
<p>Sibling elements can be accessed via the siblings combinator <span class="combinator">=</span>:</p>
<pre><span class="comment">//matches all the subject elements that are siblings of<br />//the message element(s)</span><br /><span class="selector">message</span> <span class="combinator">=</span> <span class="selector">subject</span> { }</pre>
</div>
<div class="sub comp">
<h4 class="title"><span class="number"><a href="#n1.4.4" id="n1.4.4">1.4.4</a></span> Next and previous siblings combinators</h4>
<p>Use the next siblings combinator <span class="combinator">+</span> and previous siblings combinator <span class="combinator">-</span> if you want to access elements following or preceding (in the <em>current</em> tree order) a specified element in the same scope.</p>
<pre><span class="comment">//this will match the message element(s) following a from sibling</span>
<span class="selector">from</span> <span class="combinator">+</span> <span class="selector">message</span> { }
<span class="comment">//this will match the subject element(s) preceding a message sibling</span>
<span class="selector">message</span> <span class="combinator">-</span> <span class="selector">subject</span> { }</pre>
<p><em>Note:</em> For further instructions on how to select amongst the following or preceding elements read the <a href="#n1.5">filters, flags and splitters</a> chapter.</p>
</div>
<div class="sub yet">
<h4 class="title"><span class="number"><a href="#n1.4.5" id="n1.4.5">1.4.5</a></span> Accessing elements laid out in lines</h4>
<p>Containers that are in flow might be laid out in various lines and subjacent lines of elements. You can target them by the use of the line combinator. By placing a filter or the universal selector after the pipe you can select lines of elements in a container. </p>
<pre><span class="comment">//this will select all the lines of elements inside of the
//document element</span>
<span class="selector">document</span> <span class="combinator">|</span> <span class="selector">*</span> { }
<span class="comment">//this will select only the first line</span>
<span class="selector">document</span> <span class="combinator">|</span> <span class="filter">:first</span> { }</pre>
<p>To select elements inside the matched line(s) you have to use a second pipe, like so:</p>
<pre><span class="comment">//this selects the last element in the first line of elements</span>
<span class="selector">document</span> <span class="combinator">|</span> <span class="filter">:first</span> <span class="combinator">|</span> <span class="filter">:last</span> { }</pre>
<p>You can drill down into the secondary lines (hierarchically) that have been formed according to the layout algorithm using the child combinator.</p>
<pre><span class="comment">//this will select all the subjacent lines inside of the first
//line of elements</span>
<span class="selector">document</span> <span class="combinator">|</span> <span class="filter">:first</span> <span class="selector">*</span> { }</pre>
#TODO <a href="https://github.com/AXR/Specification/issues/37">37</a>
<p>Since each line is a somewhat abstract concept - there is no element representing each line, if you create new elements in the scope of a line, only one element per line will be created, and not one per selected element, and it will be attached to the parent element. On the other hand, properties applied in the scope of the line will be applied to all elements in that line. </p><p>The <a href="#n1.3.7.4">parent object</a> will refer to the parent line, in case of a subjacent line, or the parent element, in case of a line.</p>
</div>
<div class="sub yet">
<h4 class="title"><span class="number"><a href="#n1.4.6" id="n1.4.6">1.4.6</a></span> Content text combinator</h4>
<p>Many times you will want to access a part of an element's content text—a word, or a particular line, for example—rather than its container.</p><p>Consider this snippet of XML code:</p>
<pre class="xml"><<span class="selector">document</span>>
<<span class="selector">paragraph</span>>This is a line of dummy text. Lorem ipsum
dolor sit amet, consectetur adipiscing elit.</<span class="selector">paragraph</span>>
</<span class="selector">document</span>></pre>
<p>First, we have to understand what happens with the content text when it is rendered. An element is represented by a container, think of it as an amount of space in the rendered document and inside it the content text and the containing elements. The default height of the container is the height of its content.</p>
<p>When the width of the container is not wide enough to accommodate all its content text, wrapping occurs. This means that the text is split in various lines of text, and therefore the height increases. Now there are two or more blocks stacked over each other.</p>
<p>Conceptually, the text can be further split into elements. Each word is preceded, followed, or surrounded by whitespace. Furthermore, each character (letter, kanji…) of that word is a separate glyph you can refer to.</p>
<p><img alt="Graphic explaining the concept of lines, words and glyphs" src="/images/accessing_content_text.png" /></p>
<p>To select portions of text, the content text combinator is used. After the combinator, you write a string to specify what part of the text you want to select.</p>
<pre><span class="comment">//this will select any occurrence of "dummy text" and set
//its height to 15 points</span>
<span class="combinator">..</span> <span class="selector">*</span> <span class="combinator">></span> <span class="string">"dummy text"</span> { <span class="property">height</span>: <span class="number">15</span> }
<span class="comment">//this will only match the first one</span>
<span class="combinator">..</span> <span class="selector">*</span> <span class="combinator">></span> <span class="string">"dummy text"</span><span class="filter">:first</span> { <span class="property">height</span>: <span class="number">15</span> }</pre>
<p>The universal selector permits to select text elements by type (lines, words or glyphs):</p>
<pre><span class="comment">//this will select all lines (the entire content text)</span>
<span class="selector">document</span> <span class="selector">paragraph</span> <span class="combinator">></span> <span class="selector">*</span> { }
<span class="comment">//this will select the first line of text</span>
<span class="selector">document</span> <span class="selector">paragraph</span> <span class="combinator">></span> <span class="selector">*</span><span class="filter">:first</span> {}</pre>
<p>To access a word, you use the content text combinator and universal selector again, after selecting a portion of the text:</p>
<pre><span class="selector">document</span>
{
    <span class="comment">//this will select the last word of the content text</span>
    <span class="selector">paragraph</span> <span class="combinator">></span> <span class="selector">*</span> <span class="combinator">></span> <span class="selector">*</span><span class="filter">:last</span> { }
    <span class="comment">//this is equivalent, since the universal selector can be
    //omitted in this case</span>
    <span class="selector">paragraph</span> <span class="combinator">>></span> <span class="filter">:last</span> { }
}</pre>
<p>You repeat the same pattern again to select a glyph:</p>
<pre><span class="selector">document</span>
{
    <span class="comment">//this will select the first letter of the content text</span>
    <span class="selector">paragraph</span> <span class="combinator">></span> <span class="selector">*</span> <span class="combinator">></span> <span class="selector">*</span> <span class="combinator">></span> <span class="selector">*</span><span class="filter">:first</span> { }
    <span class="comment">//this is equivalent</span>
    <span class="selector">paragraph</span> <span class="combinator">>>></span> <span class="filter">:first</span> { }
}</pre>
<p>The <a href="#s_each">each splitter</a> permits the separation of each text elements (either lines, words or glyphs) that would otherwise be joined in the same selection:</p>
<pre><span class="selector">document</span>
{
<span class="comment">//this will select each line of text and give it vertical margins,
//increasing the line spacing</span>
<span class="selector">paragraph</span> <span class="combinator">></span> <span class="selector">*</span><span class="splitter">/each</span> { <span class="property">margin</span>: @{ <span class="property">top</span>, <span class="property">bottom</span>: <span class="number">5</span> }; }
<span class="comment">//this will select the first three letters of "dummy", each separately</span>
<span class="selector">paragraph</span> <span class="combinator">>></span> <span class="string">"dummy"</span> <span class="combinator">></span> <span class="filter">:nth</span>(<span class="number">1</span>, <span class="number">3</span>)<span class="splitter">/each</span> { }
}</pre>
</div>
<div class="sub yet">
<h4 class="title"><span class="number"><a href="#n1.4.7" id="n1.4.7">1.4.7</a></span> Ancestor combinator</h4>
<p>Ancestors can be selected using the ancestor combinator <code>^^</code>. If the elements matched previously don't share the same ancestors, the combined collection of ancestors—and not the common ones—will be returned.</p>
<pre><span class="comment">//matches every ancestors of <em>important</em> elements</span>
<span class="combinator">..</span> <span class="selector">important</span> <span class="combinator">^^</span> <span class="selector">*</span> { }</pre>
</div>
</section>
<section class="chapter">
<h3 class="title"><span class="number"><a href="#n1.5" id="n1.5">1.5</a></span> Filters, flags and splitters</h3>
<p><strong>Filters</strong> are used to reduce or alter the current selection. Each individual element of the selection is checked to see if the condition(s) match(es).</p>
<p>Always remember that if used alone, the omitted universal selector is actually assumed. Filters can be appended to any other selector even allowing multiple affixed filters. For example, you could do the following:</p>
<pre><span class="comment">//this matches the first occurrence of the note element,
//if it has a child</span>
<span class="selector">note<span class="filter">:first:parent</span></span> { }</pre>
<p>Keep in mind that the order of the filters will alter the outcome, so if you put the filters of the previous example in reverse order, it will select the <em>first element that has a child</em>, instead of the <em>first element, but only if it has a child</em>.</p>
<pre><span class="comment">//this matches the first of the note elements that have a child</span>
<span class="selector">note<span class="filter">:parent:first</span></span> { }</pre>
<p>Using <strong>flags</strong> you can apply certain HSS declarations depending on an element's event state. Flags are preceded by <code>::</code> unlike filters which use <code>:</code>.</p>
<p><em>Note:</em> <a href="#n1.5.3">System flags</a> are automatically activated and deactivated: the user has no control over their default behaviour.</p>
<p>This XML sample will be used to illustrate examples throughout this chapter.</p>
<pre class="xml"><<span class="selector">notes</span>>
<<span class="selector">note</span>>
<<span class="selector">to</span>>Peter</<span class="selector">to</span>>
<<span class="selector">from</span>>James</<span class="selector">from</span>>
<<span class="selector">subject</span>>Reminder</<span class="selector">subject</span>>
<<span class="selector">message</span>>The keys are under the doormat.</<span class="selector">message</span>>
<<span class="selector">message</span>>Please don't forget to bring some wine.</<span class="selector">message</span>>
</<span class="selector">note</span>>
<<span class="selector">note</span>>
<<span class="selector">to</span>>Paul</<span class="selector">to</span>>
<<span class="selector">from</span>>Julia</<span class="selector">from</span>>
<<span class="selector">subject</span>>Rendezvous</<span class="selector">subject</span>>
<<span class="selector">message</span>>Meet me at the inn.</<span class="selector">message</span>>
</<span class="selector">note</span>>
</<span class="selector">notes</span>></pre>
<div class="sub part">
<h4 class="title"><span class="number"><a href="#n1.5.1" id="n1.5.1">1.5.1</a></span> Position filters</h4>
<p>The following filters are used to select a subset of elements, depending on their position in the <em>current</em> tree order.</p>
<p>In the case of several matched parents the filters refer to the <strong>combined collection</strong> returned whereas their <em class="monospace">Child</em> variant to the children's position <strong>inside their own parent</strong>.</p>
<p>The <strong><a id="f_first">first and firstChild filters</a></strong> match the first element(s).</p>
<pre><span class="comment">//this matches the first <em>to</em> element in our example</span>
notes note <span class="filter">:first</span> { }
<span class="comment">//this matches the first <em>to</em> elements of each <em>note</em> element in our example</span>
notes note <span class="filter">:firstChild</span> { }
<span class="comment">//which is equivalent to appending the <a href="#s_each">each splitter</a> to the former</span>
notes note <span class="splitter">/each</span><span class="filter">:first</span> { }</pre>
<p>The <strong><a id="f_last">last and lastChild filters</a></strong> match the last element(s).</p>
<pre><span class="comment">//this matches the last element in the second <em>note</em> element</span>
notes note <span class="filter">:last</span> { }
<span class="comment">//this matches the last element<u>s</u> of each <em>note</em> element</span>
notes note <span class="filter">:lastChild</span> { }</pre>
<p>The <strong><a id="f_even">even and evenChild filter</a></strong> select elements whose index is even (the count starts with 1).</p>
<pre><span class="comment">//in our example this matches the <em>from</em> element in the first <em>note</em> element
//but not the one in the second <em>note</em> element (7 isn't even)</span>
notes note from<span class="filter">:even</span> { }
<span class="comment">//in our example this matches the fourth <em>message</em> element<u>s</u> of the <em>note</em> elements</span>
notes note message<span class="filter">:evenChild</span> { }</pre>
<p>The <strong><a id="f_odd">odd and oddChild filters</a></strong> select elements whose index is odd (the count starts with 1).</p>
<pre><span class="comment">//this matches the 1st <em>to</em> element in our example</span>
notes note to<span class="filter">:odd</span> { }
<span class="comment">//this matches the 1st <em>to</em> elements of each <em>note</em> element in our example</span>
notes note to<span class="filter">:oddChild</span> { }</pre>
<p>The <strong><a id="f_nth">nth and nthChild filters</a></strong> select elements which index matches a number or expression, meets a condition or falls within a given range.</p>
<pre><span class="comment">//this matches the fourth element in the collection</span>
<span class="filter">:nth</span>(<span class="number">4</span>) { }
<span class="comment">//if there are at least 6 elements currently in the collection,
//it matches the element after every 5th one; if not it matches the 5th one</span>
<span class="filter">:nth</span>(5n + 1 | <span class="number">5</span>) { }
<span class="comment">//this matches elements whose index is ≥ 3 in the collection</span>
<span class="filter">:nth</span>(>= <span class="number">3</span>) { }
<span class="comment">//this matches elements whose index is 5, 10 or 15 in the collection</span>
<span class="filter">:nth</span>(5n, <span class="number">15</span>) { }
<span class="comment">//this matches elements whose index is 1, 2, 3 and ≥ 8 in the collection</span>
<span class="filter">:nth</span>(<span class="number">1</span>, <span class="number">3</span> & <span class="number">8</span>, *) { }</pre>
</div>
<div class="sub part">
<h4 class="title"><span class="number"><a href="#n1.5.2" id="n1.5.2">1.5.2</a></span> Hierarchy filters</h4>
<p>You can filter elements by their relationship with the other elements in the tree.</p>
<p>The <strong>parent filter</strong> matches every element that is a parent, which means that it has at least one child. If the element is an ancestor it will always also be a parent.</p>
<pre><span class="comment">//this matches childless elements</span>
<span class="modifier">!</span><span class="filter">:parent</span> { }</pre>
<p>The <strong>has filter</strong> matches elements which have certain children, descendants, ancestors or siblings.</p>
<pre><span class="comment">//this matches elements that are parent of at least one <em>message</em> element</span>
<span class="filter">:has</span>(<span class="selector">message</span>) { }
<span class="comment">//this matches elements that are an ancestor of a <em>message</em> element</span>
<span class="filter">:has</span>(<span class="combinator">..</span> <span class="selector">message</span>) { }
<span class="comment">//this matches elements that are a descendant of a <em>message</em> element</span>
<span class="filter">:has</span>(<span class="combinator">^^</span> <span class="selector">message</span>) { }
<span class="comment">//this matches elements which have at least one <em>message</em> sibling</span>
<span class="filter">:has</span>(<span class="combinator">=</span> <span class="selector">message</span>) { }
<span class="comment">//this matches elements which have at least one <em>message</em> sibling following them</span>
<span class="filter">:has</span>(<span class="combinator">+</span> <span class="selector">message</span>) { }
<span class="comment">//this matches elements which have at least one <em>message</em> sibling preceding them</span>
<span class="filter">:has</span>(<span class="combinator">-</span> <span class="selector">message</span>) { }</pre>
</div>
<div class="sub part">
<h4 class="title"><span class="number"><a href="#n1.5.3" id="n1.5.3">1.5.3</a></span> System flags</h4>
<p>You usually want to provide some kind of feedback to the user when he/she is using your site. Targeting elements using flags is an easy way to add interactivity to the site, to create a compelling user experience.</p>
<p>The <strong>hover flag</strong> targets only elements that are lying under the cursor.</p><pre><span class="comment">//matches every element which has the mouse over it (even overlaid ones)</span>
<span class="flag">::hover</span> { }</pre>
<p>The <strong>press flag</strong> targets only elements which are lying under the mouse pointer while the primary button is pressed (usually the left one) or during an hold event (an unreleased touch event).</p><pre><span class="comment">//matches every element which is being pressed</span>
<span class="flag">::press</span> { }</pre>
<p>The <strong>drag flag</strong> targets only elements which are being dragged (multiple elements can be dragged at the same time using a multi-touch interface device).</p><pre><span class="comment">//matches every element that is being dragged</span>
<span class="flag">::drag</span> { }</pre>
<p>The <strong>target flag</strong> targets elements which are a potential landing point for the currently dragged element(s).</p>
<pre><span class="comment">//matches all elements that are actual dragging destination
//for the currently dragged element(s)</span>
<span class="flag">::target</span> { }
<span class="comment">//which is equivalent to</span>
<span class="flag">::target(*)</span> { }
<span class="comment">//this will match while a <em>file</em> sibling is being dragged</span>
<span class="flag">::target(file)</span> { }</pre>
<p><em>Note:</em> If you want to match a dragging destination which is currently hovered by a dragged element you just need to append the hover flag: the drop target will be matched when any part of the combined boundary of the dragged element and the contact area of the input device touches it.</p>
<pre><span class="comment">//matches every dragging destination elements when a dragged
//element is over it</span>
<span class="flag">::target::hover</span> { }</pre>
<p>The <strong>focus flag</strong> matches the element that currently receives user input (through tabbing for example).</p>
<pre><span class="comment">//matches every element which receives user input</span>
<span class="flag">::focus</span> { }</pre>
<p>The <strong>select flag</strong> matches either elements, lines, words or characters that are currently selected. It ceases if a click or a tap occurs afterward.</p>
<pre><span class="comment">//matches elements which are currently selected</span>
<span class="flag">::select</span> { }
<span class="comment">//matches the characters that are currently selected</span>
* <span class="combinator">>>></span> <span class="flag">::select</span> { }</pre>
</div>
<div class="sub yet">
<h4 class="title"><span class="number"><a href="#n1.5.4" id="n1.5.4">1.5.4</a></span> The attribute filter</h4>
<p>You can filter elements based on their attributes using the <strong>attribute filter</strong>.</p>
<pre>
<span class="comment">//matches elements which have a title attribute</span>
:[title] { }
<span class="comment">//matches elements which have a title AND an href attribute</span>
:[title]:[href] { }
<span class="comment">//matches elements which have a title OR an href attribute</span>
:[title, href] { }
<span class="comment">//which is equivalent to</span>
:[title], :[href] { }</pre>
</div>
<div class="sub yet">
<h4 class="title"><span class="number"><a href="#n1.5.5" id="n1.5.5">1.5.5</a></span> Text matching filters</h4>
<p>These filters select elements which text—either the content text or the value of the attribute(s)—matches a given string, condition or pattern.</p>
<p>The <strong>contains filter</strong> matches elements that contain a given string in their texts.</p>
<pre><span class="comment">//matches every element whose content text contains "reminder"
//regardless of the case</span>