summaryrefslogtreecommitdiff
path: root/memos/WM-086.txt
diff options
context:
space:
mode:
authornetop://ウィビ <paul@webb.page>2026-04-11 14:24:49 -0700
committernetop://ウィビ <paul@webb.page>2026-04-11 14:24:49 -0700
commit8c34d810af95fae0ef846f54370a8c88bfab7123 (patch)
tree436beaf30f7b2b3f15741dd54a37e313964d1f7d /memos/WM-086.txt
initial commitHEADprimary
Diffstat (limited to 'memos/WM-086.txt')
-rw-r--r--memos/WM-086.txt271
1 files changed, 271 insertions, 0 deletions
diff --git a/memos/WM-086.txt b/memos/WM-086.txt
new file mode 100644
index 0000000..97c5f1b
--- /dev/null
+++ b/memos/WM-086.txt
@@ -0,0 +1,271 @@
+
+
+
+
+
+
+
+Document: WM-086 P. Webb
+Category: Programming 2026-03-24
+
+ How to write CSS
+
+Abstract
+
+ CSS is about structure and design, the code should reflect that.
+
+Body
+
+ I've been writing HTML and CSS for 20+ years at the time of this
+ writing. Along the way I've learned, discovered, and refined the way
+ I write CSS. In 2026, I'm so glad I don't need Sass anymore, as much
+ as I enjoyed writing it; nested code and variables are now readily
+ available in browsers without a precompilation step. Success!
+
+ However, I still run into codebases where the CSS irritates tf outta
+ me. I'm not just talking random projects on Github, I mean in Fortune
+ 500 companies too. LLMs regurgitate bad practices so for all the new
+ coders discovering the joy and beauty of web development, here's some
+ tips from someone who survived the BEM syntax era and completely
+ side-stepped the "let's just chain variables" frenzy that's still
+ pervasive today.
+
+ What follows are examples of what I consider to be poorly written CSS
+ and how I fix them:
+
+ ```css
+ .board_icon {
+ text-align: center;
+ padding: 8px 4px 0px 4px;
+ width: 60px;
+ flex-shrink: 0;
+ }
+ .board_icon a {
+ display: inline;
+ }
+ .board_icon a:hover, .board_icon a:focus{
+ text-decoration: none;
+ }
+ .board_icon a::before {
+ display: inline;
+ font-family: "Font Awesome 6 Free";
+ font-size: 2em;
+ content: "\f086";
+ }
+ .board_icon a.board_on::before {
+ font-weight: 900;
+ }
+ .board_icon a.board_on2::before {
+ font-weight: 900;
+ }
+ .board_icon a.board_off::before {
+ font-weight: 400;
+ }
+ .board_icon a.board_redirect::before {
+ font-weight: 900;
+ content: "\f061";
+ }
+ ```
+
+ This physically pains me (if I look at it too long). Inconsistent
+ indentation and lack of space between rules are the most egregrious
+ errors in this for me, but you also have rules that can be
+ consolidated and a unit specifier on a zero value (`0px` is
+ unnecessary, just use `0`). Finally, the rules aren't in
+ alphabetical order.
+
+ Computers and browsers don't care but for humans, code you can scan
+ quickly is important for collaboration; even if that collaborator is
+ future you! Don't you wanna make future you's life at least a lil'
+ bit easier?
+
+ Here's how I would rewrite that code block:
+
+ ```css
+ .board_icon {
+ flex-shrink: 0;
+ padding: 8px 4px 0 4px;
+ text-align: center;
+ width: 60px;
+
+ a {
+ display: inline;
+
+ &::before {
+ content: "\f086";
+ display: inline;
+ font-family: "Font Awesome 6 Free";
+ font-size: 2rem;
+ }
+
+ &:focus,
+ &:hover {
+ text-decoration: none;
+ }
+
+ &.board_off::before {
+ font-weight: 400;
+ }
+
+ &.board_on,
+ &.board_on2,
+ &.board_redirect {
+ &::before {
+ font-weight: 900;
+ }
+ }
+
+ &.board_redirect::before {
+ content: "\f061";
+ }
+ }
+ }
+ ```
+
+ You might've noticed I replaced the `2em` `font-size` with `2rem`.
+ This is more of an aesthetic choice. Elastic Measure (`em`) and Root
+ Elastic Measure (`rem`) are similar in that they scale based on
+ something but `em` scales based on the parent element whereas `rem`
+ scales based on the root (`html`) font size.
+
+ When I'm building sites, I want everything to be cohesive and scale
+ uniformly. That way, when I decide to change the root font size, my
+ entire site won't look wonky.
+
+ Here's a list of other things I've seen in the particular codebase
+ I'm rewriting for my forum theme:
+
+ - `margin:0 0 10px 0;`: no space after the colon
+ - `border-color :rgb(199, 195, 191);`: space before the colon but not
+ after? Why?
+ - `border-top: 1px solid RGB(255, 255, 255);`: why is `RGB` all caps
+ here but not in the previous line? Why use `rgb` at all when this
+ could be represented as `#fff` or simply `white`?
+ - `font-weight: bold;` and `font-weight: 700;`: these both mean bold
+ and there's only system fonts declared so why specify `700` and not
+ `600` (the default)?
+ - `margin-top: 5px !important;`: if you have to use `!important;`,
+ something's wrong. It's possible this theme is trying to override
+ some styling of the core forum software so I'm willing to let this
+ slide but then again, proper nesting would eliminate the need
+ for this.
+ - `background: #fdfdfd;`: unless you also have a background image and
+ positioning, you should always use `background-color`.
+ Specificity wins.
+ - `font: 9px/15px verdana, sans-serif;`: I don't like this for a few
+ reasons. First, `font-size` and `line-height` are just easier to
+ read and should be declared in parent elements. Per element rules
+ like this leads to eventual divergence and tech debt. Second, the
+ font name is lowercase here and regular case elsewhere. Like so:
+ `font-family: Verdana, Helvetica, Arial, sans-serif;` and this is
+ applied to an `h1`, which makes sense to have a different font as
+ it's a headline. I rarely use `font` and the rare times I do, it's
+ to do `font: inherit` (browsers by default have buttons and inputs
+ use different fonts).
+ - `padding: 10px 10px;`: redundant; this is telling us that there's
+ 10 pixels of padding to the top and bottom, as well as left and
+ right. This could be rewritten as `padding: 10px;` (10 pixels of
+ padding all around).
+
+ Now, there are certain conditions where I don't necessarily use
+ alphabetical order and that's when there are rule pairs present.
+
+ - `width` / `height`
+ - `margin` / `padding`
+ - `top` / `left` / `bottom` / `right`
+
+ Here's a simple example:
+
+ ```css
+ .profile_hd {
+ width: 2rem; height: 2rem;
+
+ &::before {
+ width: 100%; height: 100%;
+
+ background-image: url("../images/emoji/bust_in_silhouette_3d.png");
+ background-size: contain;
+ }
+ }
+ ```
+
+ And a more involved one (using CSS variables from my palette[1]). I
+ left the `color: rgb` rule in there because I haven't decided what to
+ replace it with (I don't like mixing color rules, stay consistent...
+ similarly, I'm not sure that `margin-top` needs to be there...oh and
+ `&::before` and `&::after` are grouped together in that order because
+ it makes sense):
+
+ ```css
+ ul {
+ background-color: var(--uchu-yang);
+ border: 1px solid var(--uchu-gray-3);
+ border-radius: 4px;
+ box-shadow: 3px 3px 4px oklch(var(--uchu-yin-raw) / 30%);
+ color: rgb(83, 100, 130);
+ line-height: 2.2rem;
+ margin-top: 2px;
+ min-width: 18.2rem;
+ padding: 0.5rem;
+ position: absolute;
+ z-index: 90;
+
+ &::before,
+ &::after {
+ width: 0; height: 0;
+
+ border-left: 0.5rem solid transparent;
+ border-right: 0.5rem solid transparent;
+ content: "";
+ position: absolute;
+ }
+
+ &::before {
+ top: -0.5rem; left: 1.25rem;
+ border-bottom: 0.5rem solid var(--uchu-yang);
+ }
+
+ &::after {
+ top: calc(calc(0.5rem + 1px) * -1); left: 1.25rem;
+
+ border-bottom: 0.5rem solid var(--uchu-gray-3);
+ z-index: -1;
+ }
+ }
+ ```
+
+ You can see `width` and `height` together at the top of a rule block,
+ separated by a blank line because there are multiple rules after
+ that. However, in the standalone `&::before` block, there's no blank
+ line after `top` and `left` because that'd look silly. The `&::after`
+ block has more than one rule after `top` and `left` so those lines
+ are grouped together.
+
+ I've dabbled in trying to get Prettier to format my CSS files back
+ when I was in the Node.js ecosystem, with middling results. I'm sure
+ I could get Claude to make a formatter to my specifications...hmm,
+ side project for now.
+
+ There are situations where I may have something like `padding: 1rem;`
+ and also have `margin-right: 2rem`. I wouldn't put these together
+ because of the `-right`. Non-dashed specifiers are in alphabetical
+ order like everything else (including `padding` in this instance).
+
+ This codebase has a lot of styling on IDs, which is something I don't
+ do. For me, IDs are for HTML and JavaScript, not styling; either use
+ the element name and style against that or apply a class to
+ said element.
+
+ For naming elements, I prefer using a dash or two and relying on
+ nesting (no more than three levels) when necessary. For this project,
+ I'm beholden to the existing HTML syntax in PHP files. They'll get
+ updated over time.
+
+ I'm probably missing a lot but this is just off the top of my head.
+ Multi-trillion-dollar corporations perpetuate these terrible code
+ choices too but at least in my personal projects I can have a curated
+ and maintainable experience. 🕸️
+
+References
+
+ [1] <https://uchu.style>