clairity.css 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -20,12 +20,6 @@ CLASSES - Here is where we first deviate from the classless CSS directive. We'll
20
20
  // #containers -
21
21
  // -------------------------------------------------------------------------- */
22
22
 
23
- /* this doesn't work because some items aren't full width, like asides
24
- body > *:not(.fluid) {
25
- margin-inline: var(--m);
26
- }
27
- */
28
-
29
23
  /* for constraining width to a reasonable line length - keep in sync
30
24
  with sectioning children of the body element in components.css */
31
25
  .readable {
@@ -38,52 +32,43 @@ body > *:not(.fluid) {
38
32
  ._100vw, [class~="100vw"] {
39
33
  width: 100vw;
40
34
  max-width: 100vw; /* still has horizontal scrollbar issues */
41
- margin-inline: calc(50% - 50vw - var(--xs));/*neg. margin if needed*/
35
+ margin-inline: calc(50% - 50vw); /* neg. margin where necessary */
42
36
  }
43
37
 
44
- /* #100dvi - dynamic full width of the viewport */
38
+ /* #100dvi - full dynamic viewport width - unfortunately doesn't account for
39
+ scrollbars, so its utility for full-bleed breakouts is severely limited
40
+ ...........................................................................*/
45
41
  ._100dvi, [class~="100dvi"] {
46
- /*width: 100dvi;*/
42
+ width: 100dvi;
47
43
  max-width: 100dvi; /* still has horizontal scrollbar issues */
48
- /*margin-inline: calc(50% - 50dvi - var(--xs));neg margin if needed*/
44
+ margin-inline: calc(50% - 50dvi); /* neg. margin where necessary */
49
45
  }
50
46
 
51
47
 
52
48
  /* -----------------------------------------------------------------------------
53
- // #grid helpters -
49
+ // #grid - subgrid is ff 71+ & safari 16+ only, chrome/edge in dev - 20230423
54
50
  // -------------------------------------------------------------------------- */
55
51
 
56
- /* .subgrid extends grid into descendents - firefox 71+ & safari 16+ only, no
57
- chrome/edge yet - EXPERIMENTAL
52
+ /* .subgrid extends grid into descendents - EXPERIMENTAL
58
53
  ...........................................................................*/
59
54
  .subgrid {
60
- grid-column: padded; /* place subgrid on the parent grid */
61
- display: inherit; /* inherits grid, otherwise no subgrid */
62
- grid-template-columns: subgrid; /* only subgrid columns */
63
- gap: inherit; /* inherit parent grid gap */
64
- max-width: unset; /* let parent grid dictate width */
55
+ grid-column: padded; /* place subgrid on the parent grid */
56
+ display: inherit; /* inherits grid, otherwise no subgrid */
57
+ grid-template-columns: subgrid; /* only subgrid columns */
58
+ gap: inherit; /* inherit parent grid gap */
59
+ max-width: unset; /* let parent grid dictate width */
65
60
  }
66
61
 
67
- /* HACK: chrome & edge do not yet support subgrid as of 20221001 */
68
- @supports not (grid-template-columns: subgrid) {
69
- .subgrid { display: contents; }
70
- .subgrid :first-child { /* TODO: this breaks some layouts, like banner images */
71
- /*grid-column-start: 2;*/ /* TODO: fix right side guttering too */
72
- }}
73
-
74
62
  /* span the full width of the grid
75
63
  .......................................................................... */
76
64
  .full {
77
- /*grid-column: full;*/
78
- grid-column: 1 / -1;
79
- max-width: none; /* remove other width restrictions */
65
+ grid-column: 1 / -1; /* more foolproof than `full` grid area */
66
+ /*max-width: none;*/ /* interferes with .full in .subgrid */
80
67
  }
81
68
 
82
69
  /* span all but the 1st & last grid columns
83
70
  .......................................................................... */
84
- .padded {
85
- grid-column: 2 / -2;
86
- }
71
+ .padded { grid-column: 2 / -2; } /* 1st/last columns are typically padding */
87
72
 
88
73
 
89
74
  /* -----------------------------------------------------------------------------
@@ -101,6 +86,13 @@ body > *:not(.fluid) {
101
86
  .h6 { --min-font: 1; --max-font: 1.125; }
102
87
  .h5, .h6 { font-weight: var(--bold); }
103
88
 
89
+ /* dampen the prominence of links in headings; keep in sync with cosmetic.css */
90
+ :where(.h1, .h2, .h3, .h4, .h5, .h6) :is(a, :visited) {
91
+ color: var(--heading);
92
+ font-weight: unset;
93
+ text-decoration-style: dotted;
94
+ }
95
+
104
96
  /* text providing extra detail to a heading. p-subtitle is a microformat
105
97
  (plaintext) alternative class name for .subtitle
106
98
  // .......................................................................... */
@@ -125,27 +117,14 @@ body > *:not(.fluid) {
125
117
 
126
118
 
127
119
  /* -----------------------------------------------------------------------------
128
- // #colors - provide a set of utility color classes where the --color variable
129
- // is employed - EXPERIMENTAL
120
+ // #colors - semantic classes for setting the --color variable - EXPERIMENTAL
130
121
  // -------------------------------------------------------------------------- */
131
122
 
132
- /* semantic colors for states */
123
+ /* semantic colors for icon states */
133
124
  .valid { --color: var(--valid); }
134
125
  .invalid { --color: var(--invalid); }
135
126
  .unknown { --color: var(--unknown); }
136
127
 
137
- .red { --color: var(--error); }
138
- .orange { --color: var(--error); }
139
- .yellow { --color: var(--warning); }
140
- .lime { --color: var(--error); }
141
- .green { --color: var(--success); }
142
- .aqua { --color: var(--error); }
143
- .blue { --color: var(--info); }
144
- .indigo { --color: var(--error); }
145
- .purple { --color: var(--error); }
146
- .violet { --color: var(--error); }
147
- .magenta { --color: var(--error); }
148
-
149
128
 
150
129
  /* -----------------------------------------------------------------------------
151
130
  // #backgrounds -
@@ -153,79 +132,27 @@ body > *:not(.fluid) {
153
132
 
154
133
  /* https://css-tricks.com/background-patterns-simplified-by-conic-gradients/ */
155
134
  .checkerboard {
156
- background: repeating-conic-gradient(var(--neutral) 0% 25%,
157
- transparent 0% 50%) 50% / 20px 20px;
158
- }
159
-
160
- /* -----------------------------------------------------------------------------
161
- // #spacing -
162
- // -------------------------------------------------------------------------- */
163
-
164
- /* for inserting an icon using the background-blend-mode technique */
165
- .icon {
166
- display: inline-block;
167
- padding-right: var(--inline-padding);
168
- background-size: var(--text-icon);
169
- background-position: var(--center-right);
170
- background-blend-mode: lighten, normal;
171
- }
172
-
173
- /* leading space for inline ::before elements, typically icons */
174
- .leading {
175
- padding-left: var(--inline-padding);
135
+ background: repeating-conic-gradient(var(--neutral) 0% 25%,
136
+ transparent 0% 50%) 50% / 20px 20px;
176
137
  }
177
138
 
178
- /* trailing space for inline ::after elements, typically icons */
179
- .trailing {
180
- padding-right: var(--inline-padding);
181
- }
182
139
 
183
140
  /* -----------------------------------------------------------------------------
184
141
  // #layout -
185
142
  // -------------------------------------------------------------------------- */
186
143
 
187
- /* a grid with columns of width var(--column)
188
- // .......................................................................... */
189
- .grid {
190
- display: grid;
191
- grid-template-columns: [full-start] repeat(auto-fit,
192
- minmax(var(--column), 1fr)) [full-end];
193
- column-gap: var(--m);
194
- container-type: none; /* containment clashes with grid on safari */
195
- }
196
-
197
144
  /* main content placement in the holy grail 3-column grid
145
+ // firefox is not forgiving with :has() rules, so this must be separated out
198
146
  // .......................................................................... */
199
- /* firefox is not forgiving with :has() rules, so this must be separated out */
200
147
  .dual-aside { grid-column: 2 / -2; }
201
148
 
202
149
 
203
- /* a basic flex container
204
- ............................................................................ */
205
- .flex {
206
- --flex-break: 100rem; /* TODO/TEMP - a bit of a magical number */
207
- display: flex;
208
- flex-wrap: wrap;
209
- gap: var(--m);
210
- }
211
-
212
- /* flex all the children of .flex to single column below --flex-break */
213
- :where(.flex) > * { /* [0000] specificity */
214
- flex-grow: 1;
215
- flex-basis: calc((var(--flex-break) - 100%) * 999);
216
- }
217
-
218
- .flex > :where(.column, .main) {
219
- /*flex: 1 1 auto;*/
220
- }
221
-
222
-
223
150
  /* -----------------------------------------------------------------------------
224
151
  // #breaks - #br #wbr #hr - line breaks and the horizontal rule
225
152
  // -------------------------------------------------------------------------- */
226
153
 
227
- /* #hr #section - the sectioning horizontal rule - [0011] specificity */
228
- hr.section {
154
+ /* #sectioning - a significant break between sections */
155
+ .sectioning {
229
156
  height: 3rem;
230
157
  margin: auto;
231
158
  width: unset;
@@ -240,9 +167,26 @@ hr.section {
240
167
 
241
168
 
242
169
  /* -----------------------------------------------------------------------------
243
- // #icons - convenience classes for icons defined in icons.css - EXPERIMENTAL
170
+ // #icons - helper classes for icons - EXPERIMENTAL
244
171
  // -------------------------------------------------------------------------- */
245
172
 
173
+ /* for inserting an icon using the background-blend-mode technique */
174
+ .icon {
175
+ display: inline-block;
176
+ padding-right: var(--inline-padding);
177
+ background-size: var(--text-icon);
178
+ background-position: var(--center-right);
179
+ background-blend-mode: lighten, normal;
180
+ }
181
+
182
+ /* leading/trailing space for inline ::before elements, typically icons
183
+ // TODO: investigate using :has() for this on the parent of .icon
184
+ // ........................................................................... */
185
+ .leading { padding-left: var(--inline-padding); }
186
+ .trailing {padding-right: var(--inline-padding); }
187
+
188
+ /* convenience classes for icons defined in icons.css
189
+ // ........................................................................... */
246
190
  .i-burger { --icon: var(--i-burger); }
247
191
  .i-check { --icon: var(--i-check); }
248
192
  .i-chevron { --icon: var(--i-chevron); }
@@ -258,7 +202,8 @@ hr.section {
258
202
  .i-user-circle { --icon: var(--i-user-circle); }
259
203
  .i-user-off { --icon: var(--i-user-off); }
260
204
 
261
- /* #unadorned removes a ::before or ::after icon - [0011] specificity */
205
+ /* removes a ::before or ::after icon - [0011] specificity
206
+ // ........................................................................... */
262
207
  .unadorned::before, .unadorned::after {
263
208
  content: unset;
264
209
  }
@@ -9,22 +9,22 @@
9
9
  // -------------------------------------------------------------------------- */
10
10
 
11
11
  /* #body - auto-grid by default - overrides base.css default body definition.
12
- set --columns to the number of columns desired */
12
+ set --columns to the number of columns desired
13
+ // .......................................................................... */
13
14
  body {
14
15
  display: grid;
15
16
  grid-template-columns: [full-start] var(--padding, var(--m))
16
17
  [padded-start] repeat(var(--columns, auto-fit),
17
18
  minmax(var(--grid), 1fr)) [padded-end]
18
19
  var(--padding, var(--m)) [full-end];
19
- column-gap: var(--gap); /* flexible between 400 - 800px */
20
+ column-gap: var(--gap); /* --gap is fluid between 400 - 800px */
20
21
  max-width: unset;
21
22
  }
22
23
 
23
24
  /* some containers should span full or padded width by default if in the grid */
24
- :where(:not(.grid)) > main { grid-column: padded; }
25
- nav, header, footer {
26
- grid-column: full;
27
- }
25
+ :where(:not(.grid)) > main { grid-column: padded; }
26
+ nav, header, footer { grid-column: full; }
27
+
28
28
 
29
29
  /* the top header typically should sit flush to the top of the page and use
30
30
  padding; TODO: this seems to be over-specified */
@@ -39,11 +39,39 @@ footer {
39
39
  grid-auto-rows: min-content; /* don't unnecessarily expand rows */
40
40
  column-gap: var(--m);
41
41
  container-type: unset; /* safari doesn't like contain with grid */
42
- padding-inline: var(--padding, var(--m)); /* flexible padding */
42
+ /*padding-inline: var(--padding, var(--m));*/ /* flexible padding */
43
43
  }
44
44
 
45
45
  footer > p { grid-column: 1 / -1; } /* take up a whole row in the grid */
46
46
 
47
+ /* HACK: because .100dvi uses a negative margin hack to break out of the parent
48
+ container and extra negative margin to compensate for the vertical scrollbar,
49
+ the content needs more padding on narrower screens to stay visible */
50
+ body > footer:last-of-type:is(._100dvi, [class~="100dvi"]) {
51
+ margin-inline: calc(50% - 50dvi - var(--s));
52
+ padding-inline: var(--m) var(--s); /* asymmetric due to neg. margin;
53
+ centers because --m is twice --s & --s used above */
54
+ }
55
+
56
+ /* a basic flex container
57
+ // .......................................................................... */
58
+ .flex {
59
+ --flex-break: 100rem; /* TODO/TEMP - a bit of a magical number */
60
+ display: flex;
61
+ flex-wrap: wrap;
62
+ gap: var(--m);
63
+ }
64
+
65
+ /* flex all the children of .flex to single column below --flex-break */
66
+ :where(.flex) > * { /* [0000] specificity */
67
+ flex-grow: 1;
68
+ flex-basis: calc((var(--flex-break) - 100%) * 999);
69
+ }
70
+
71
+ .flex > :where(.column, .main) {
72
+ /*flex: 1 1 auto;*/
73
+ }
74
+
47
75
 
48
76
  /* -----------------------------------------------------------------------------
49
77
  // #headings -
@@ -53,13 +81,15 @@ header:not(.banner) {
53
81
  display: flex;
54
82
  flex-wrap: wrap;
55
83
  justify-content: space-between;
84
+ align-items: baseline; /* make sure flexed text lines up visually*/
56
85
  }
57
86
 
58
87
  header :where(h1,h2,h3,h4,h5,h6) {
59
88
  }
60
89
 
61
- header :where(p) {
62
- flex: 1 0 100%;
90
+ /* use <span>, not <p>, for text that sits alongside a heading within a header*/
91
+ header :where(p, .subtitle) {
92
+ flex: 1 0 100%; /* flex to a full row, forcing a line wrap*/
63
93
  }
64
94
 
65
95
 
@@ -91,7 +121,8 @@ header :where(p) {
91
121
  grid-column: unset;
92
122
  flex-direction: column;
93
123
  flex-grow: 1; /* take up the whole role if orphaned */
94
- flex-basis: calc((40vw - 100%) * 999);
124
+ /* flex-basis unnecessary? seems to wrap weirdly at larger viewport widths */
125
+ /*flex-basis: calc((40vw - 100%) * 999);*/
95
126
  align-items: start; /* some items will float otherwise */
96
127
  row-gap: var(--s); /* add some vertical spacing */
97
128
  justify-content: start;
@@ -139,7 +170,7 @@ header :where(p) {
139
170
 
140
171
 
141
172
  /* -----------------------------------------------------------------------------
142
- // #icons - svg icons
173
+ // #i #icons - standalone svg icons
143
174
  // -------------------------------------------------------------------------- */
144
175
 
145
176
  i[class^='i-'] {
@@ -154,6 +185,7 @@ i[class^='i-'] {
154
185
 
155
186
  /* -----------------------------------------------------------------------------
156
187
  // #banner - header that usually includes a hero image and perhaps a nav
188
+ // uses the grid `place-items: center` technique on all children
157
189
  // -------------------------------------------------------------------------- */
158
190
 
159
191
  .banner {
@@ -164,6 +196,7 @@ i[class^='i-'] {
164
196
  grid-template-areas: "banner";
165
197
  place-items: center;
166
198
  align-self: flex-start;
199
+ max-width: unset; /* override header max-width in cosmetic.css */
167
200
  height: var(--banner-height);
168
201
  /*max-height: var(--banner-max-height);*/
169
202
  /*background-color: var(--primary-transparent);*/ /* bg color was meant
@@ -176,20 +209,30 @@ i[class^='i-'] {
176
209
  /*.banner menu { margin-block: var(--ml); }*/
177
210
 
178
211
  /* banner #content - constrain content width with a css variable set on parent*/
179
- .banner .content { width: var(--content-width); }
212
+ .banner .content {
213
+ width: var(--content-width);
214
+ max-width: 100dvi; /* don't let content overflow viewport */
215
+ z-index: 0; /* safari uses source order otherwise */
216
+ }
180
217
 
181
218
  /* banner grid */
182
219
  .banner > * { grid-area: banner; }
183
220
  .banner > nav {
184
- place-self: start center;
221
+ place-self: flex-start center;
185
222
  width: var(--line-length);
223
+ max-width: 100dvi; /* make sure nav doesn't go off-screen */
186
224
  }
187
225
  .banner nav menu { /*flex: auto;*/ }
188
226
 
227
+ /* TODO: use fluid padding on non-hero children rather than container query? */
228
+ @container (width <= 50rem) {
229
+ .banner > :not(img, .hero) { padding-inline: var(--s); }
230
+ }
231
+
189
232
  .banner > img, .hero {
190
233
  height: min(var(--banner-height), var(--banner-max-height));
191
234
  width: 100%;
192
- max-width: none;
235
+ max-width: none; /* TODO: should this be broken out separately?*/
193
236
  z-index: -1;
194
237
  }
195
238
 
@@ -295,7 +338,7 @@ body > nav a, body > header > nav a {
295
338
  max-height: 2.75rem;
296
339
  }
297
340
  /* visited links in the nav menu shouldn't be different colors */
298
- :where([aria-label="primary"], nav menu li) a:visited { color: var(--link); }
341
+ :where([aria-label="primary"], nav menu li) :visited { color: var(--link); }
299
342
 
300
343
  /*body > nav a.button, body > header > nav a.button {
301
344
  white-space: nowrap;
@@ -312,6 +355,7 @@ body > nav a, body > header > nav a {
312
355
  outline: none;
313
356
  border: none;
314
357
  width: var(--height); /* form icons are square */
358
+ max-width: 100cqi;
315
359
  min-width: 0;
316
360
  padding: 0;
317
361
  cursor: pointer; /* unconventional usage for 'clickable' */
@@ -559,7 +603,7 @@ button.tertiary, .tertiary.button { /* [0011] / [0020] specificity */
559
603
  // .......................................................................... */
560
604
 
561
605
  /* TODO: the main form grid should inline elements rather than forcing it here
562
- .bottons inlines/wraps multiple buttons where necessary - [0010] specificity*/
606
+ .buttons inlines/wraps multiple buttons where necessary - [0010] specificity*/
563
607
  .buttons {
564
608
  list-style: none;
565
609
  display: flex; /* overwrite display: grid; */
@@ -580,11 +624,12 @@ form .buttons { max-width: var(--field-max) }
580
624
  .roomy.buttons { gap: var(--ml); }
581
625
 
582
626
  /* fix buttons floating and getting squished at smaller screen widths */
583
- @container (max-width: 28rem) {
627
+ @container (width <= 28rem) {
584
628
  form { max-width: unset; }
585
629
  form .buttons {
586
- max-width: unset;
587
- grid-column: -1/1;
630
+ max-width: unset; /* don't constrain width in narrow confines */
631
+ grid-column: -1/1; /* span the entire grid for more room */
632
+ justify-content: flex-end; /* end-align looks more natural than start*/
588
633
  }
589
634
  label { font-size: var(--small); }
590
635
  }
@@ -654,6 +699,18 @@ nav:has(.toggle[aria-expanded=false]) > menu {
654
699
  [rel~="external"].button:hover::after { background-color: var(--foreground); }
655
700
 
656
701
 
702
+ /* #button_to - a rails class set on forms that look like buttons - minimize the
703
+ // form width while maximizing the button within to that form width
704
+ // .......................................................................... */
705
+ .button_to {
706
+ width: min-content;
707
+ /*HACK: an inline-size container-type make forms zero-width, so make it normal*/
708
+ container-type: normal;
709
+ }
710
+ .button_to > [type="submit"] {
711
+ width: max-content;
712
+ }
713
+
657
714
 
658
715
  /* -----------------------------------------------------------------------------
659
716
  // #selectmenu - Open UI replacement to the standard select element -
@@ -728,7 +785,7 @@ selectmenu::part(listbox) {
728
785
  margin-top: auto; /* make sure buttons are at the bottom */
729
786
  }
730
787
 
731
- @container (min-width: 35rem) {
788
+ @container (width >= 35rem) {
732
789
  /*.card { flex-direction: row; }*/ /* interferes with single-card section */
733
790
  .card > img, .cards > article > img {
734
791
  max-height: var(--width);
@@ -741,19 +798,6 @@ selectmenu::part(listbox) {
741
798
  }
742
799
  }
743
800
 
744
- /* TEMP: use media queries for browsers that don't support container queries */
745
- @supports not (container-type: inline-size) {
746
- @media (min-width: 47rem) {
747
- /*.card { flex-direction: row; }*/ /* interferes with single-card section */
748
- .card > img, .cards > article > img {
749
- max-height: var(--width);
750
- max-width: var(--width);
751
- }
752
- .cards :last-child:nth-child(3n - 2) {
753
- grid-column-end: span 3;
754
- flex-direction: row;
755
- }
756
- }}
757
801
 
758
802
  /* -----------------------------------------------------------------------------
759
803
  // #tags - an inline list of metatags; can be text, links, icons, or other
@@ -767,7 +811,8 @@ selectmenu::part(listbox) {
767
811
  padding: 0;
768
812
  }
769
813
 
770
- .tags > li {
814
+ /* TODO: .tag should be in classes.css and kept in sync with this rule? */
815
+ .tags > li, .tag {
771
816
  display: inline-block;
772
817
  color: var(--secondary);
773
818
  font-size: var(--small);
@@ -789,12 +834,6 @@ selectmenu::part(listbox) {
789
834
  margin-bottom: var(--m);
790
835
  }
791
836
 
792
- /* TEMP: add margin-top to buttons for browsers that don't support :has() */
793
- @supports not (:has(a)) {
794
- .tags + .buttons {
795
- margin-top: var(--m);
796
- }}
797
-
798
837
 
799
838
  /* -----------------------------------------------------------------------------
800
839
  // #grid - multi-column grid adjustments
@@ -810,12 +849,6 @@ selectmenu::part(listbox) {
810
849
  container-type: none; /* containment clashes with grid on safari */
811
850
  }
812
851
 
813
- /* for layouts with left & right asides, put main in the middle grid columns */
814
- /* grrr, firefox is not forgiving with :has() rules, so this must be separated*/
815
- .dual-aside {
816
- grid-column: 2 / -2;
817
- }
818
-
819
852
  /*full is a grid area for a row that spans all columns - [0000] specificity */
820
853
  :where(.grid) > :where(header,hgroup,h1,h2,h3,h4,h5,h6,nav:not(.column),footer){
821
854
  grid-column: full;
@@ -907,7 +940,7 @@ selectmenu::part(listbox) {
907
940
  // #progressbar - a circular progress bar component - from almond.css
908
941
  // -------------------------------------------------------------------------- */
909
942
 
910
- [role="progressbar"] {
943
+ [role="progressbar"] {
911
944
  --value: 50;
912
945
  --thick: 50%;
913
946
  --medium: 58%;