1
1
<script >
2
-
2
+ import Prism from ' svelte-prism ' ;
3
3
</script >
4
4
5
- <p >Yadda yadda made this pretty cool!</p >
5
+ <p >
6
+ I tend to find from project to project I need the same handful of helper classes. Whenever
7
+ possible I use mixins to generate these helpers due to the ease of maintenance—it's nice to
8
+ be able to add or remove additional classes to a range.
9
+ </p >
10
+
11
+ <h4 >The Helper Loop</h4 >
12
+
13
+ <p >
14
+ This is the classic mixin I use for generating helper classes, which I just call the helper loop:
15
+ </p >
16
+
17
+ <Prism >
18
+ {` // e.g. .a-1 {z-index:1} .a-2 {z-index:2} .a-3 {z-index:3}
19
+ @mixin helper-loop($start, $stop, $step, $class-name, $property, $unit, $unit-start: false,
20
+ $unit-step: false, $extend: "") {
21
+
22
+ $i: $start;
23
+
24
+ @if not $unit-start {
25
+ $unit-start: $start;
26
+ }
27
+
28
+ @if not $unit-step {
29
+ $unit-step: $step;
30
+ }
31
+
32
+ $value: $unit-start;
33
+
34
+ @while $i <= $stop {
35
+
36
+ .#{$class-name}-#{$i} {
37
+ #{$property}: #{$value}#{$unit}!important;
38
+ };
39
+
40
+ @if ($extend != "") {
41
+ .#{$class-name}-#{$i} { @extend #{$extend} }
42
+ }
43
+
44
+ $value: $value + $unit-step;
45
+
46
+ $i: $i + $step;
47
+
48
+ }
49
+ } ` }
50
+ </Prism >
51
+
52
+ Let's take a look at an example for generating some margin classes. First is the more simple
53
+ example, where <code >.margin-15</code > gives a value of <code >margin: 15px</code >:
54
+
55
+ <Prism >
56
+ {` @include helper-loop(0, 15, 5, 'margin', 'margin', 'px'); ` }
57
+ </Prism >
58
+
59
+ Or maybe we want to abstract the numerical value on the helper class from the unit itself, so
60
+ <code >.margin-4</code >
61
+ to get <code >margin: 1rem</code >:
62
+
63
+ <Prism >
64
+ {` @include helper-loop(0, 4, 1, 'margin', 'margin', 'rem', 0, .25); ` }
65
+ </Prism >
66
+
67
+ With fonts maybe we want to skip the odd numbers:
68
+
69
+ <Prism >
70
+ {` @include helper-loop(8, 36, 2, 'font-size', 'font-size', 'rem', 0.625, 0.125); ` }
71
+ </Prism >
72
+
73
+ <p >
74
+ I like to have the number on the end of the helper class line up with the pixel size of a font, as
75
+ it's easier to visualize what the result will be. So in this case <code >font-size-12</code > might
76
+ be <code >1em</code >, but visually I want that to be the same as <code >12px</code >.
77
+ </p >
78
+
79
+ <p >
80
+ Sometimes I'll setup two loops next to each other. Maybe I want a few odd number font sizes in
81
+ that bread in butter range of 11–17 pixels:
82
+ </p >
83
+
84
+ <Prism >
85
+ {` @include helper-loop(8, 36, 2, 'font-size', 'font-size', 'rem', 0.625, 0.125);
86
+ @include helper-loop(11, 17, 2, 'font-size', 'font-size', 'rem', 0.6875, 0.125); ` }
87
+ </Prism >
88
+
89
+ <p >
90
+ I like to have some classes to nudge elements using <code >position: relative;</code >, but I really
91
+ just want to use a single helper class to do this like <code >.top-1</code >. This is where that
92
+ <code >extend</code > parameter comes in:
93
+ </p >
94
+
95
+ <Prism >
96
+ {` .relative {
97
+ position: relative;
98
+ }
99
+
100
+ @include helper-loop(1, 5, 1, 'top', 'top', 'px', false, false, ".relative"); ` }
101
+ </Prism >
102
+
103
+ <p >
104
+ Then all I need is one class to nudge an element <span class =" bottom-2" >up</span > or
105
+ <span class =" bottom-2" />. I love this one for icons which rarely have the same visual baseline as
106
+ text:
107
+ </p >
108
+
109
+ <Prism language =" html" >
110
+ {` Then all I need is one class to nudge an element <span class="bottom-2">up</span> or <span class="bottom-2"></span> ` }
111
+ </Prism >
112
+
113
+ <h4 >Responsive Classes</h4 >
114
+
115
+ <p >
116
+ Building out responsive classes is more complex. I use a loop in a loop to do this. I also don't
117
+ use a global mixin for this like the other helpers, preferring to copy, paste and modify an
118
+ existing loop.
119
+ </p >
120
+
121
+ <p >
122
+ I'll use one of my spacing loops to demonstrate. Let's start with just one helper class to
123
+ understand what we are creating:
124
+ </p >
125
+
126
+ <Prism language =" css" >
127
+ {`
128
+ .col-margin-1 > * {
129
+ margin-left: .25rem;
130
+ margin-right: .25rem;
131
+ }
132
+ .col-margin-1 > *:first-child {
133
+ margin-left: 0;
134
+ }
135
+ .col-margin-1 > *:last-child {
136
+ margin-right: 0;
137
+ }
138
+ ` }
139
+ </Prism >
140
+
141
+ <p >
142
+ Having child selectors and psuedo selectors complicates this enough that I can't use my helper
143
+ loop mixin, and responsive classes further complicate matters. First thing I need is a map of my
144
+ breakpoints. I like to match my breakpoints to what Bootstrap uses as they're easy to commit to
145
+ memory:
146
+ </p >
147
+
148
+ <Prism >
149
+ {` $bootstrap-breakpoints: (
150
+ 'xs': 0,
151
+ 'sm': 576px,
152
+ 'md': 768px,
153
+ 'lg': 992px,
154
+ 'xl': 1200px,
155
+ 'xxl': 1400px,
156
+ ); ` }
157
+ </Prism >
158
+
159
+ <p >
160
+ I want to be able to pass parameters into a function of some sort and have that spit out all the
161
+ helper classes for me. That function call will look like this:
162
+ </p >
163
+
164
+ <Prism >{` @include spacing-loop(.25, 4, 'margin'); ` }</Prism >
165
+
166
+ <p >
167
+ I'm going to be calling this loop a couple of times to generate <code >.col-margin-8</code >,
168
+ <code >.col-margin-12</code >
169
+ and <code >.col-margin-16</code >. So there is a hidden parameter of
170
+ <code >$spacing-breakpoints</code > which is map of all the breakpoints I want to generate classes for.
171
+ </p >
172
+
173
+ <Prism >
174
+ {` $spacing-breakpoints: 'xs', 'sm'; // 'md', 'lg', 'xl', 'xxl'; ` }
175
+ </Prism >
176
+
177
+ <p >Next we need to generate each of the media breakpoints:</p >
178
+
179
+ <Prism >
180
+ {` @mixin spacing-breakpoint-loop($property, $i, $value, $breakpoints) {
181
+
182
+ @each $breakpoint in $breakpoints {
183
+
184
+ @media (min-width: map-get($bootstrap-breakpoints, $breakpoint)) {
185
+ @include spacing-styles($property, $i, $value, $breakpoint);
186
+ }
187
+
188
+ }
189
+
190
+ } ` }
191
+ </Prism >
192
+
193
+ <p >This means our last mixin has the actual classes and instructions in it:</p >
194
+
195
+ <Prism >
196
+ {` @mixin spacing-styles($property, $i, $value, $breakpoint) {
197
+
198
+ @if $breakpoint == 'xs' {
199
+ $breakpoint: '';
200
+ }
201
+ @else {
202
+ $breakpoint: '-#{$breakpoint}';
203
+ }
204
+
205
+ .col-#{$property}#{$breakpoint}-#{$i} > * {
206
+ #{$property}-left: calc(#{$value}rem / 2);
207
+ #{$property}-right: calc(#{$value}rem / 2);
208
+ }
209
+ .col-#{$property}#{$breakpoint}-#{$i} > *:first-child {
210
+ #{$property}-left: 0
211
+ }
212
+ .col-#{$property}#{$breakpoint}-#{$i} > *:last-child {
213
+ #{$property}-right: 0
214
+ }
215
+ } ` }
216
+ </Prism >
217
+
218
+ <p >
219
+ The only thing I want to call out here is the check for the smallest possible breakpoint of <code
220
+ >'xs'</code
221
+ >. The media query applies to any screen size which 0px and above, which means that class applies
222
+ to all screen sizes and we don't need to designate those classes as <code >'-xs-'</code >.
223
+ </p >
224
+
225
+ <p >To close this out I'm going to include the entire <code >_spacing.scss</code > file. Keep in mind that I have <code >$bootstrap-breakpoints</code > as global variable for all my <code >scss</code > files, but I'll include here for simplicity:</p >
226
+
227
+ <Prism >
228
+ {` /* Child Spacing
229
+ * Stuff to generate a helper classes for setting the spacing on all child elements.
230
+ */
231
+
232
+ /* EXAMPLE: .col-margin-1 or .row-margin-1 or .row-padding-1 or .col-margin-12 */
233
+ // You get 1, 2, 3, 4, 8, 12, 16. Padding isn't enabled (so enable if needed). Jump to end of file.
234
+
235
+ // This should be a global variable available to all scss files.
236
+ $bootstrap-breakpoints: (
237
+ 'xs': 0,
238
+ 'sm': 576px,
239
+ 'md': 768px,
240
+ 'lg': 992px,
241
+ 'xl': 1200px,
242
+ 'xxl': 1400px,
243
+ );
244
+
245
+ // Add the breakpoints as they are needed: 'xs', 'sm', 'md', 'lg', 'xl', 'xxl'
246
+ $spacing-breakpoints: 'xs'; //, 'sm', 'md', 'lg', 'xl', 'xxl';
247
+
248
+ @mixin spacing-styles($property, $i, $value, $breakpoint) {
249
+
250
+ @if $breakpoint == 'xs' {
251
+ $breakpoint: '';
252
+ }
253
+ @else {
254
+ $breakpoint: '-#{$breakpoint}';
255
+ }
256
+
257
+ .col-#{$property}#{$breakpoint}-#{$i} > * {
258
+ #{$property}-left: calc(#{$value}rem / 2);
259
+ #{$property}-right: calc(#{$value}rem / 2);
260
+ }
261
+ .col-#{$property}#{$breakpoint}-#{$i} > *:first-child {
262
+ #{$property}-left: 0
263
+ }
264
+ .col-#{$property}#{$breakpoint}-#{$i} > *:last-child {
265
+ #{$property}-right: 0
266
+ }
267
+
268
+ .row-#{$property}#{$breakpoint}-#{$i} > * {
269
+ #{$property}-top: calc(#{$value}rem / 2);
270
+ #{$property}-bottom: calc(#{$value}rem / 2);
271
+ }
272
+ .row-#{$property}#{$breakpoint}-#{$i} > *:first-child {
273
+ #{$property}-top: 0
274
+ }
275
+ .row-#{$property}#{$breakpoint}-#{$i} > *:last-child {
276
+ #{$property}-bottom: 0
277
+ }
278
+ }
279
+
280
+ @mixin spacing-breakpoint-loop($property, $i, $value, $breakpoints) {
281
+
282
+ @each $breakpoint in $breakpoints {
283
+
284
+ @media (min-width: map-get($bootstrap-breakpoints, $breakpoint)) {
285
+ @include spacing-styles($property, $i, $value, $breakpoint);
286
+ }
287
+
288
+ }
289
+
290
+ }
291
+
292
+ @mixin spacing-loop($amount, $steps, $property, $start: false) {
293
+
294
+ $i: 1;
295
+
296
+ @if $start {
297
+ $i: $start;
298
+ }
299
+
300
+ $value: $amount;
301
+
302
+ @while $i <= $steps {
303
+
304
+ @include spacing-breakpoint-loop($property, $i, $value, $spacing-breakpoints);
305
+
306
+ $value: $value + $amount;
307
+
308
+ $i: $i + 1;
309
+ }
310
+ }
311
+ // Example: .col-margin-1
312
+ @include spacing-loop(.25, 4, 'margin');
313
+ @include spacing-loop(2, 8, 'margin', 8); // For 2rem
314
+ @include spacing-loop(3, 12, 'margin', 12); // For 3rem
315
+ @include spacing-loop(4, 16, 'margin', 16); // For 4rem
316
+
317
+ // Enable if needed.
318
+ // @include spacing-loop(.25, 4, 'padding'); ` }
319
+ </Prism >
0 commit comments