clairity.css 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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%;