More writing on the rationale and critique of CSS. Started to include other demos from other frameworks like Carousel from bootstrap.

master
Zed A. Shaw 4 years ago
parent c1873ab1bd
commit b7ff702bbd
  1. 6
      public/build/bundle.css
  2. 4413
      public/build/bundle.js
  3. 2
      public/build/bundle.js.map
  4. 66
      public/code/Carousel.css
  5. 14
      public/code/Carousel.html
  6. 16
      public/test.css
  7. 25
      public/test.html
  8. 1
      src/App.svelte
  9. 46
      src/FAQ.svelte
  10. 377
      src/Home.svelte
  11. 95
      src/demos/Carousel.svelte
  12. 6
      src/demos/index.svelte
  13. 4
      src/routes.js
  14. 92
      src/thumbs/Carousel.svelte

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,66 @@
content {
border: 1px solid #ddd;
display: flex;
flex-direction: column;
flex: flex-grow;
padding: 1rem;
}
carousel {
outline: 2px solid green;
position: relative;
}
carousel figure {
display: none;
}
carousel figure.active {
display: flex;
position: relative;
flex-direction: column;
outline: 1px solid red;
}
carousel figure img {
width: 100%;
}
carousel figure figcaption {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 2em;
background: var(--color-bg-secondary);
opacity: 0%;
}
carousel figure figcaption:hover {
opacity: 90%;
}
carousel next,prev {
position: absolute;
bottom: 0;
opacity: 0%;
height: 100%;
display: flex;
flex-direction: column;
align-content: center;
justify-content: center;
}
carousel next {
right: 0;
}
carousel prev {
left: 0;
}
carousel next:hover,prev:hover {
opacity: 60%;
background-color: var(--color-bg);
}

@ -0,0 +1,14 @@
<carousel>
<figure class="active">
<img alt="Stock photo" src="{ holder(16 * 40,9 * 40) }">
<figcaption>Image 1</figcaption>
</figure>
<!-- this image is not seen until set active -->
<figure>
<img alt="Stock photo" src="{ holder(16 * 40,9 * 40) }">
<figcaption>Image 2</figcaption>
</figure>
<prev><Icon name="arrow-left" size="48" /></prev>
<next><Icon name="arrow-right" size="48" /></next>
</carousel>

@ -0,0 +1,16 @@
button {
padding: 1rem;
background-color: blue;
color: white;
font-size: 2rem;
}
button.main {
background-color: orange;
}
#again {
background-color: yellow;
}

@ -0,0 +1,25 @@
<html>
<head>
<title>Test of Cascade</title>
<link rel="stylesheet" href="/test.css">
<style>
button {
background-color: green;
}
.attempt {
background-color: red;
}
</style>
</head>
<body>
<h1>HI!</h1>
<button>Sky Blue</button>
<button id="again" class="attempt main">Broken Button</button>
</body>
</html>

@ -31,6 +31,7 @@
</a> </a>
<ul> <ul>
<li><a href="/demos" use:link>Demos</a></li> <li><a href="/demos" use:link>Demos</a></li>
<li><a href="/faq" use:link>FAQ</a></li>
</ul> </ul>
</nav> </nav>
</header> </header>

@ -0,0 +1,46 @@
<style>
h1 {
font-size: 3em;
}
</style>
<section>
<h1>FAQ</h1>
</section>
<h2>Why did you do this?</h2>
<p>It started as an attempt to relearn modern CSS for myself so I can teach others. As I did this I realized that most of the things I learned have been completely replaced with flexbox and grids, and if I just use those then CSS becomes much easier to understand. Specificity works as expected. When I change a component with <b>class</b> or <b>id</b> it actually changes. The layout flows correctly and is easier to create. Nearly everything works better and is easier to understand.
</p>
<p>This website became a demonstration to others that <b>layout</b> doesn't need <b>div.class</b> structure, subverting <b>ul/li</b> tags, and other CSS hacks. You can use simple <b>truly semantic</b> HTML and simple CSS to accomplish 90% of what you're doing today with more reliable results faster.
</p>
<h2>Why is this site in black and white?</h2>
<p>I used an entirely monochrome simplified design because I'm not a designer, and I want people to focus on the visual structure of each demo, not whether my use of Cornflower Blue was appropriate for a button.
</p>
<p>I'm also an experienced oil painter and a fundamental teaching in realist art is that color does not matter for visual comprehension. What matters most is the "drawing", or monochrome aspects of visual experience. If you can't make something work in monochrome then no amount of color will help. Make it visually understandable in monochrome and any color scheme you choose should work (barring a few rules about color perception's relationship to monochrome values).
</p>
<h2>What's wrong with classes?</h2>
<p>There's nothing wrong with classes in CSS. How they're used in recent CSS frameworks subverts the normal specificity rules making CSS unnecessarily difficult. The original specificity rules put the base design of a component at the tag level, then a <b>class</b> can be used to modify and extend the design, and an <b>id</b> can make this even more specific. In today's use of <b>div.class</b> heavy markup you lose this ability to alter the design as needed where its used, and instead you have to resort to <b>!important</b> and specificity hacking to change how something looks, or add more <b>div</b> with more <b>class</b>.</p>
<p>The other problem with <b>div.class</b> is it's more difficult to debug problems with the layout. There's the obvious problem of debugging failures in layout through a forest of divs, but you're also relying on specificity that can come from anywhere in the cascade. It's much more difficult to find exactly <b>what</b> bit of CSS is overriding your local decisions. If you've ever had to open the inspector in your browser to troll through CSS locations looking for the culprit then that's why. If the base design decisions are at the tag level, then your local <b>class</b> and <b>id</b> specifics will work as expected. You can also replace many uses of class as design modifiers with scoped CSS variables and reduce the use of <b>div.class</b> even further.</p>
<p>Finally, using <b>div.class</b> heavy layout systems pollutes your markup with structure that's difficult to analyze and maintain. When you focus on using <b>truly</b> semantic named tags and follow specificity as intended then your HTML is lighter and easier to understand because it isn't full of <b>div.grid.col-1.col-mx-auto</b> class rules that really have nothing to do with the actual meaning of that particular visual element. With <b>flexbox</b> and <b>CSS grids</b> you don't need any layout divs, and can keep the HTML clean and semantic. This also ends up being more flexible with less or the same effort as using a pre-made grid system full of divs.</p>
<h2>Should we ban div.class?</h2>
<p>Hell no. The current problem of <b>too much</b> class based CSS is because of trends in recent years calling for everyone to irrationally ban some practice. Remember when everyone decided tables were evil? So then we banned tables and <b>grids</b> completely? Then nobody could do a layout without crazy tricks and JavaScript? Nobody wants a repeat of the anti-tables "semantic markup" war, so please don't ban <b>div.class</b>.</p>
<p>All this website does is demonstrate that you don't need <b>so much div.class</b>. You can scrap a lot of what you're using now to do layout and go with clean HTML with flatter structure, then judiciously use <b>div.class</b> as needed. Treat <b>div.class</b> like salt. Right now you're pouring a whole box of it on your HTML when a little bit makes it taste better.</p>
<h2>Do these demos work on phones?</h2>
<p>They could but I haven't taken the time to make them adapt. That may come in a later release. Try it anyway
as you may be surprised how well the layouts still work on smaller screens.</p>
<h2>Can I suggest a challenge?</h2>
<p>Yes please. If you find an example of a layout that you think is impossible with flexbox and CSS grids then tell me on <a href="https://twitter.com/lzsthw">Twitter at @lzsthw</a> and I'll attempt a replica. My only requirement is that you also have to tell me what trick the challenge is using. This is an exercise in replicating layouts, not reverse engineering devious hidden CSS tricks. Also keep in mind that I am not invested in "winning" and only curious about the limits of flexbox and CSS grids. If you find something I can't do, that means I found a useful limit to avoid. It doesn't mean that we throw out all of flexbox and CSS grids so you can go back to the float-clear-div-class 1990s.
</p>

@ -26,14 +26,21 @@
padding-right: 4rem; padding-right: 4rem;
} }
h1#faq { quote {
font-size: 3em; box-shadow: 4px 4px 4px 4px var(--color-shadow);
padding: 1em;
font-style: italic;
background-color: var(--color-bg-secondary);
}
pre code {
font-size: 0.8em;
} }
</style> </style>
<hero> <hero>
<h1>fsck CSS</h1> <h1>fsck CSS</h1>
<p>An experiment in cleaning up CSS and HTML with modern tools like <b>flexbox</b> and <b>grids</b>.</p> <p>An experiment in cleaning up CSS and HTML with modern tools like <b>flexbox</b> and <b>grids</b>.</p>
</hero> </hero>
<hr> <hr>
@ -43,7 +50,7 @@
<h3>Remove Classes</h3> <h3>Remove Classes</h3>
<Icon name="code" size="64" /> <Icon name="code" size="64" />
<p>Using a classless style like <a href="https://andybrewer.github.io/mvp/">MVP.css</a>, you <p>Using a classless style like <a href="https://andybrewer.github.io/mvp/">MVP.css</a>, you
bring back CSS specificity to its original intent.</p> bring back CSS specificity to its original intent.</p>
</aside> </aside>
<aside> <aside>
@ -63,91 +70,343 @@
<rationale> <rationale>
<section> <section>
<h1>Cleaner CSS</h1> <h1>Cleaner CSS</h1>
</section> </section>
<p>This website is nothing more than a set of small demos for the idea of <p>This website is nothing more than a set of small demos for the idea of
using flexbox and grids to clean up and simplify CSS. Most everything else using flexbox and grids to clean up and simplify CSS. Most everything else
about CSS stays. Filters, transforms, attributes, and everything that about CSS stays. Filters, transforms, attributes, and everything that
applies to the visual display of the components of a design. What gets applies to the visual display of the components of a design. What gets
removed is <b>div</b> heavy, class heavy, not-semantic-at-all layout removed is <b>div</b> heavy, class heavy, not-semantic-at-all layout
systems cluttering the real information available through simple HTML systems cluttering the real information available through simple HTML
tags.</p> tags.</p>
<p>In short, if you're writing this:</p> <p>In short, if you're writing this:</p>
<section> <section>
<aside> <aside>
<pre> <pre>
&lt;div class="grid col-1"&gt; &lt;div class="grid col-1"&gt;
&lt;div class="card"&gt; &lt;div class="card"&gt;
... ...
&lt;/div&gt; &lt;/div&gt;
&lt;/div&gt; &lt;/div&gt;
</pre> </pre>
</aside> </aside>
</section> </section>
<p>You could write this if you use flexbox, grids, and variables:</p> <p>You could write this if you use flexbox, grids, and variables:</p>
<section> <section>
<aside> <aside>
<pre> <pre>
&lt;card&gt; &lt;card&gt;
... ...
&lt;/card&gt; &lt;/card&gt;
</pre> </pre>
</aside> </aside>
</section> </section>
<hr> <hr>
<section> <section>
<p>I demonstrate the idea with a series of copies of existing websites and other layout problems <p>I demonstrate the idea with a series of copies of existing websites and other layout problems
people frequently encounter. If you have a suggested layout challenge for me, then tell me on Twitter <a href="https://twitter.com/lzsthw">@lzsthw</a> and I'll give it a shot. people frequently encounter. If you have a suggested layout challenge for me, then tell me on Twitter <a href="https://twitter.com/lzsthw">@lzsthw</a> and I'll give it a shot.
</p> </p>
<a href="/demos" use:link><button>View The Demos</button></a> <a href="/demos" use:link><button>View The Demos</button></a>
</section> </section>
<hr> <hr>
<section> <h1>Discussion</h1>
<h1 id="faq">FAQ</h1>
</section> <p>We can analyze the problems with modern CSS by looking at how popular frameworks use specificity and the cascade:</p>
<ol>
<li>Relying on <b>div</b> to structure layout, which breaks the separation between display and content originally intended for CSS and HTML.</li>
<li>Relying on <b>class</b> (or worse <b>tag.class=tag</b>) which subverts the normal specificity rules originally intended to reduce duplication.</li>
<li>Relying on the vaguely defined cascade rules to dominate the entire CSS cascade using #1 and #2.</li>
</ol>
<h2>&lt;div&gt; as Structure</h2>
<p>The simplest criticism is the use of <b>div</b> as a structure element in the HTML. Take this example from <a href="https://getbootstrap.com/docs/4.0/layout/grid/">Bootstrap</a>:</p>
<pre>
<code class="language-html">
&lt;div class="container"&gt;
&lt;div class="row"&gt;
&lt;div class="col"&gt;Column&lt;/div&gt;
&lt;div class="col"&gt;Column&lt;/div&gt;
&lt;div class="w-100"&gt;&lt;/div&gt;
&lt;div class="col"&gt;Column&lt;/div&gt;
&lt;div class="col"&gt;Column&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</code>
</pre>
<p>This simple example shows how a large proportion of modern CSS frameworks rely on <b>div</b> to create structure and layouts when the <b>div</b> has absolutely nothing to do with the content. Another example from bootstrap is their image carousel:</p>
<pre>
<code class="language-html">
&lt;div id="carouselExampleSlidesOnly" class="carousel slide" data-ride="carousel"&gt;
&lt;div class="carousel-inner"&gt;
&lt;div class="carousel-item active"&gt;
&lt;img class="d-block w-100" src="..." alt="First slide"&gt;
&lt;/div&gt;
&lt;div class="carousel-item"&gt;
&lt;img class="d-block w-100" src="..." alt="Second slide"&gt;
&lt;/div&gt;
&lt;div class="carousel-item"&gt;
&lt;img class="d-block w-100" src="..." alt="Third slide"&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</code>
</pre>
<h1>Why did you do this?</h1> <p>This snippet of code is 13 lines long of which only 3 are actually image content. It also contains both <b>id</b> and <b>class</b> specificity, making it nearly impossible to override when used locally. If you compare that my Carousel demo you can see it much simpler:</p>
<p>It started as an attempt to relearn modern CSS for myself so I can teach others. As I did this I realized that most of the things I learned have been completely replaced with flexbox and grids, and if I just use those then CSS becomes much easier to understand. Specificity works as expected. When I change a component with <b>class</b> or <b>id</b> it actually changes. The layout flows correctly and is easier to create. Nearly everything works better and is easier to understand. <pre>
</p> <code class="language-html">
&lt;carousel&gt;
&lt;figure class="active"&gt;
&lt;img alt="Stock photo" src="..."&gt;
&lt;figcaption&gt;Image 1&lt;/figcaption&gt;
&lt;/figure&gt;
<p>This website became a demonstration to others that <b>layout</b> doesn't need <b>div.class</b> structure, subverting <b>ul/li</b> tags, and other CSS hacks. You can use simple <b>truly semantic</b> HTML and simple CSS to accomplish 90% of what you're doing today with more reliable results faster. &lt;!-- this image is not seen until set active --&gt;
</p> &lt;figure&gt;
&lt;img alt="Stock photo" src="..."&gt;
&lt;figcaption&gt;Image 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;prev&gt;&lt;Icon name="arrow-left" size="48" /&gt;&lt;/prev&gt;
&lt;next&gt;&lt;Icon name="arrow-right" size="48" /&gt;&lt;/next&gt;
&lt;/carousel&gt;
</code>
</pre>
<h1>Why is this site in black and white?</h1> <p>This is the same numbe of lines of code, but every line is clearly idenfitied and easy to understand. Each part of the display is named, matches its use in the display, and is semantically related to the concept of images.</p>
<p>I used an entirely monochrome simplified design because I'm not a designer, and I want people to focus on the visual structure of each demo, not whether my use of Cornflower Blue was appropriate for a button.
</p>
<p>I'm also an experienced oil painter and a fundamental teaching in realist art is that color does not matter for visual comprehension. What matters most is the "drawing", or monochrome aspects of visual experience. If you can't make something work in monochrome then no amount of color will help. Make it visually understandable in monochrome and any color scheme you choose should work (barring a few rules about color perception's relationship to monochrome values). <p>CSS was designed to be a style sheet language used for describing the presentation of a document. You can read from <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">Mozilla their own explanation as well</a>:</p>
</p>
<h1>What's wrong with classes?</h1> <quote>
While HTML is used to define the structure and semantics of your content, CSS is used to style it and lay it out. For example, you can use CSS to alter the font, color, size, and spacing of your content, split it into multiple columns, or add animations and other decorative features.
</quote>
<p>There's nothing wrong with classes in CSS. How they're used in recent CSS frameworks subverts the normal specificity rules making CSS unnecessarily difficult. The original specificity rules put the base design of a component at the tag level, then a <b>class</b> can be used to modify and extend the design, and an <b>id</b> can make this even more specific. In today's use of <b>div.class</b> heavy markup you lose this ability to alter the design as needed where its used, and instead you have to resort to <b>!important</b> and specificity hacking to change how something looks, or add more <b>div</b> with more <b>class</b>.</p> <p>The original intent of CSS--and still a major factor in its design--is that the HTML content doesn't have to change to alter the display for different situations. <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS Zen Garden</a> is the classic example of the principle, with a single HTML document being styled in many different ways using only CSS.</p>
<p>The other problem with <b>div.class</b> is it's more difficult to debug problems with the layout. There's the obvious problem of debugging failures in layout through a forest of divs, but you're also relying on specificity that can come from anywhere in the cascade. It's much more difficult to find exactly <b>what</b> bit of CSS is overriding your local decisions. If you've ever had to open the inspector in your browser to troll through CSS locations looking for the culprit then that's why. If the base design decisions are at the tag level, then your local <b>class</b> and <b>id</b> specifics will work as expected. You can also replace many uses of class as design modifiers with scoped CSS variables and reduce the use of <b>div.class</b> even further.</p> <p>The above examples from Bootstrap (and most other CSS frameworks) subverts this original CSS design by forcing you to add non-semantic <b>div</b> tags only to create a display structure (not information structure) for their CSS properties.</p>
<p>Finally, using <b>div.class</b> heavy layout systems pollutes your markup with structure that's difficult to analyze and maintain. When you focus on using <b>truly</b> semantic named tags and follow specificity as intended then your HTML is lighter and easier to understand because it isn't full of <b>div.grid.col-1.col-mx-auto</b> class rules that really have nothing to do with the actual meaning of that particular visual element. With <b>flexbox</b> and <b>CSS grids</b> you don't need any layout divs, and can keep the HTML clean and semantic. This also ends up being more flexible with less or the same effort as using a pre-made grid system full of divs.</p> <h3>The Impact</h3>
<h1>Should we ban div.class?</h1> <p>What's the impact of this <b>div.class</b> heavy design? By subverting CSS's original separation from the HTML you end up with the following usability problems:</p>
<p>Hell no. The current problem of <b>too much</b> class based CSS is because of trends in recent years calling for everyone to irrationally ban some practice. Remember when everyone decided tables were evil? So then we banned tables and <b>grids</b> completely? Then nobody could do a layout without crazy tricks and JavaScript? Nobody wants a repeat of the anti-tables "semantic markup" war, so please don't ban <b>div.class</b>.</p> <ol>
<li>Reasoning about the CSS visuals becomes more difficult due to the overlay of complicated boxes that have nothing to do with the visually perceived content.</li>
<li>Understanding the document structure is more difficult because of the semantically irrelevant structure divs adding noise.</li>
<li>Changing the structure--or even just fixing it--becomes more challenging since you have to alter <b>both</b> your own CSS <b>and</b> the HTML that uses their CSS structure divs.</li>
<li>Debugging layout issues using the browser inspector tool is more difficult because you have to troll through the entire CSS structure div tree to find the style impacting your design decision.</li>
<li>Debugging why your local design changes aren't working becomes a process of trolling through the CSS via the structure divs and slowly turning off CSS rules until you find the one breaking your design.</li>
</ol>
<p>All this website does is demonstrate that you don't need <b>so much div.class</b>. You can scrap a lot of what you're using now to do layout and go with clean HTML with flatter structure, then judiciously use <b>div.class</b> as needed. Treat <b>div.class</b> like salt. Right now you're pouring a whole box of it on your HTML when a little bit makes it taste better.</p> <p>A succinct way to put all of the above is this infection of CSS rules into the HTML document means you no longer have a single place to go when there's a problem with one, but instead have to constantly work in both to fix anything. If a button isn't the right size, you can't simply go to the CSS and fix it. You have to go to:</p>
<ol>
<li>Your local CSS</li>
<li>Your HTML with their <b>divs</b></li>
<li>Their CSS classes for each div</li>
</ol>
<p>This turns one target area for debugging the presentation (the CSS), into 3 potential interacting locations making it more difficult to solve the problem. If you stick to "layout and style is in CSS" then when you have a problem with the layout or style...you just go to the CSS.</p>
<h2>class as Configuration</h2>
<p>Let's take a look at a simple example from <a href="https://bulma.io/documentation/overview/modular/">Bulma</a> to explain what's happening:</p>
<pre>
<code class="language-html">
&lt;button class="button"&gt;
Button
&lt;/button&gt;
&lt;button class="button is-primary"&gt;
Primary button
&lt;/button&gt;
</code>
</pre>
<p>In this example we see that Bulma is using <b>both</b> tags <b>and</b> classes to style buttons. This means that Bulma effectively corrupts 2/3rds of the specificity rules for its design (not to mention is needlessly repetitive). If you used this code in a part of your app, but needed to slightly change the padding, you'd be forced to struggle with Bulma taking over 2 of the 3 slots reserved for specificity:</p>
<ol>
<li><b>button as a tag</b> means Bulma has taken over the specificity at the tag level.</li>
<li><b>class=button</b> means it's also taken the primary slot of class specificity.</li>
<li>That leaves you with <b>id</b> as your only way to modify a button, <b>!important</b>, or strange specificity hacks like doubling your <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity#The_!important_exception">classes as recommended by Mozilla.</a></li>
</ol>
<h3>Mozilla as Patient Zero</h3>
<p>Mozilla's recommendations are another source of confusion in CSS frameworks and is most likely the <b>cause of frameworks using structure divs</b>. <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity#The_!important_exception">Mozilla recommends</a> that instead of using <b>!important</b> you add a structure <b>div</b> to get one more level of specificity:</p>
<pre>
<code class="language-html">
&lt;div id="test"&gt;
&lt;span&gt;Text&lt;/span&gt;
&lt;/div&gt;
</code>
</pre>
<pre>
<code class="language-css">
div#test span &lbrace; color: green; &rbrace;
div span &lbrace; color: blue; &rbrace;
span &lbrace; color: red; &rbrace;
</code>
</pre>
<p>In this "fix" for <b>!important</b> your only choice is to wrap the component you want to modify with even more <b>div</b> structure and then create a more specific path with the new class. The problem with this fix is it overcomplicates the HTML but <b>also</b> breaks separation of content from style. Rather than keep your content in HTML, and your style in CSS, you're now forced to infect your HTML with helpers for CSS, all because someone else thinks you shouldn't use <b>!important</b> to override their classes.</p>
<p>The other odd hack they recommend is simply doubling the class:</p>
<pre>
<code class="language-css">
#myId#myId span &lbrace; color: yellow; }
.myClass.myClass span &lbrace; color: orange; }
</code>
</pre>
<p>There's no explanation regarding why this odd quirk of browsers isn't just a hack, but it's put forward as superior to the very clear <b>!important</b>. It'd be incredibly easy to miss this double-class hack if you were trying to find it in the CSS, but finding <b>!important</b> is trivial to find and fix later if you want. In fact, I can't actually see why this is better if it does the same thing as !important but in a sneaky way.</p>
<h3>The Impact</h3>
<p>The end result of these recommendations from Mozilla is people solve specificity by adding on more and more <b>divs</b> because they've used <b>class</b> everywhere and can't get around the specificity calculations any other way. You can see this in how Bulma uses extra <b>divs</b> in its forms:</p>
<pre>
<code class="language-html">
&lt;div class="field"&gt;
&lt;label class="label"&gt;Subject&lt;/label&gt;
&lt;div class="control"&gt;
&lt;div class="select"&gt;
&lt;select&gt;
&lt;option&gt;Select dropdown&lt;/option&gt;
&lt;option&gt;With options&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</code>
</pre>
<p>You have three levels of <b>divs</b> just to style a plain <b>select</b> tag. Most likely the use of classes forces Bulma to add more divs to increase specificity because they have hijacked the class <b>specificity</b> everywhere.
</p>
<p>Meanwhile, similar styling is done in <a href="https://andybrewer.github.io/mvp/">MVP.css</a> and other "classless" frameworks by using perfectly normal and valid tag based selectors:</p>
<pre>
<code class="language-css">
select &lbrace;
display: block;
font-size: inherit;
max-width: var(--width-card-wide);
border: 1px solid var(--color-bg-secondary);
border-radius: var(--border-radius);
margin-bottom: 1rem;
padding: 0.4rem 0.8rem;
&rbrace;
</code>
</pre>
<p>We can also say that <b>if</b> there is some failing of CSS that requires extra class divs then where is the explanation for this limitation? Why can't we just use a simple tag selector to completely alter the appearance of a <b>select</b>? Why is it suddenly these problems go away when I slather on a mountain of <b>divs</b>? If this is really the situation then that means CSS has a serious flaw as the "styling and layout" component of the web and everyone advocating for it needs to be honest and stop blaming others for not knowing it well enough. My understanding though is CSS is perfectly fine at styling a <b>select</b> tag all you want, and it's the way CSS is used today that's causing the problems.</p>
<h2>The Cascade</h2>
<p>At first glance most of the criticism might seem minor. Who cares if a single .class in a single .css file overrides my local CSS? That'd be fairly easy to find right? Where this turns into a usability nightmare is when <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade">the cascade</a> is added to the system. The cascade's purpose is to allow for CSS styles to come from different sources, but combine in a kind of hierarchy of importance. From <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade">Mozilla's documentation</a> we can see an initial problem:</p>
<quote>
<p>Only CSS declarations, that is property/value pairs, participate in the cascade. This means that at-rules containing entities other than declarations, such as a @font-face rule containing descriptors, don't participate in the cascade. In these cases, only the at-rule as a whole participates in the cascade: here, the @font-face identified by its font-family descriptor. If several @font-face rules with the same descriptor are defined, only the most appropriate @font-face, as a whole, is considered.</p>
<p>While the declarations contained in most at-rules — such as those in @media, @document, or @supports — participate in the cascade, declarations contained in @keyframes don't. As with @font-face, only the at-rule as a whole is selected via the cascade algorithm.</p>
<p>Finally, note that @import and @charset obey specific algorithms and aren't affected by the cascade algorithm.</p>
</quote>
<p>So the cascade combines properties from <b>different sources</b> but only properties that aren't @at-rules containing <em>descriptors</em>, and @import or @charset follow another set of rules entirely. Got it? Great. So easy and consistent, and we're not done yet.</p>
<p>Mozilla goes on to define the order these rules are processed (minus all the edge cases of @at-rules):</p>
<quote>
<ol>
<li>It first filters all the rules from the different sources to keep only the rules that apply to a given element.</li>
<li>Then it sorts these rules according to their importance, that is, whether or not they are followed by !important, and by their origin.</li>
<li>In case of equality, the specificity of a value is considered to choose one or the other.</li>
</ol>
</quote>
<p>What is this ordering of rules? Why a handy list in this order (which isn't clearly described as being in most or least important ordering):</p>
<quote>
<ol>
<li>user agent == normal</li>
<li>user == normal</li>
<li>author == normal</li>
<li>animations == </li>
<li>author == !important</li>
<li>user == !important</li>
<li>user agent == !important</li>
<li>transitions</li>
</ol>
</quote>
<p>However, these calculations are completely pointless because <b>user style sheets have been slowly phased out.</b> A "user style" is a piece of CSS that someone who is <b>using</b> a browser adds--on their own computer--to change the defaults set by the <b>author</b> of the site. The catch is, Chrome <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=347016">does not support user style sheets</a>, and it's the most popular browser. That means they are completely dead for practical purposes. That leaves the user agent, which is usually reset by designers anyway, and "author" styles which is simply, <b>"all of the CSS you write"</b>.</p>
<p>The confusing part of this description is it makes it <b>seem</b> like someone writing a web page is having to contend with these rules that include user styles when you actually have zero control over them, so they don't matter. The real calculations for practical purposes should be (from least to most important):</p>
<ol>
<li>Sort by !important.</li>
<li>Sort by specificity.</li>
<li>Sort by order, later wins over earlier.</li>
</ol>
<p>That's it. User agent styles are so low level they are easily replaced with a reset style. No user agents have !important rules (that I know of), and if they do this means you probably can't change them anyway. You can't control user styles as that's added by the user out of your control, so trying to add them to your calculations is meaningless. That leaves only the rules for cascade precedence in the CSS you write, and this simplifies the ordering.</p>
<p>Remember how you were admonished to never use <b>!important</b>? If you follow that edict, then, that means we finally arrive at only two sorting rules:</p>
<ol>
<li>Sort by specificity.</li>
<li>Sort by order, later wins over earlier.</li>
</ol>
<p>But finally, the last rule of sorting by order is <b>only if there's a tie</b> in the previous sorting. That means there's really only 1 rule, or maybe 1.5 rules, where you sort by specificity only and then order wins in a tie.</p>
<h2>The Impact</h2>
<p>I call these simplified practical rules the "real cascade" because they're the practical sorting rules you actually have to deal with, and they also help finally describe how modern CSS breaks this sorting cascade to make CSS harder:</p>
<ol>
<li>If we sort by !important, but nobody uses !important, then the only sorting done is by specificity.</li>
<li>If we sort by specificity 99% of the time, then modern CSS forces itself into the second highest priority of the sorting calculation leaving no room for your own local <b>class</b> or <b>tag</b> styles.</li>
<li>If we then sort by order of declaration <b>on specificity ties</b> it doesn't matter because #2 means the CSS framework will win unless we add an additional structure div to increase specificity, use the double-class trick, or add !important (which everyone says not to do).</li>
</ol>
<p>Effectively, this situation promotes CSS frameworks winning over your own styles, encourages convoluted nested <b>div</b> structure to hack specificity, and complicates cascade calculations needlessly by changing the priority of an author style that uses <b>div.class</b> such that it's difficult to modify design elements locally.</p>
<h2>An Alternative Approach</h2>
<p>Can we simplify CSS usage to avoid as many pitfalls as possible while still allowing for modern visual presentation? Since CSS lacks clear rules for the cascade, and has overly complicated rules governing the calculations of specificity using these unclear cascade rules, a good approach is to simply avoid as many of these rules as possible. We can do this by realizing that...we can just not use most of this:</p>
<ol>
<li><b>Simplify specificity</b> by using tag selectors (aka type selectors) instead <b>classes</b>.</li>
<li><b>Simplify HTML</b> by using actual <b>&lt;tags&gt;</b> instead of <b>&lt;div.class="basically-a-tag"&gt;</b>.</li>
<li><b>Simplify layout and HTML</b> by using flexbox and CSS grids instead of convoluted structure <b>divs</b>.</li>
<li><b>Simplify visual reasoning</b> by naming tags to match their actual role in the visual display.</li>
<li><b>Simplify interactions</b> by using <b>class</b> sparingly for variants or state changes.</li>
<li><b>Simplify extension and modification</b> by using <b>id</b> for specific local elements that have their own style changes overriding the previous definitions.</li>
<li><b>Simplify development</b> by adding more complicated CSS <b>after</b> you get simpler CSS working.</li>
</ol>
Links:
https://www.w3.org/TR/CSS22/cascade.html#specificity
<h1>Do these demos work on phones?</h1>
<p>They could but I haven't taken the time to make them adapt. That may come in a later release. Try it anyway
as you may be surprised how well the layouts still work on smaller screens.</p>
<h1>Can I suggest a challenge?</h1>
<p>Yes please. If you find an example of a layout that you think is impossible with flexbox and CSS grids then tell me on <a href="https://twitter.com/lzsthw">Twitter at @lzsthw</a> and I'll attempt a replica. My only requirement is that you also have to tell me what trick the challenge is using. This is an exercise in replicating layouts, not reverse engineering devious hidden CSS tricks. Also keep in mind that I am not invested in "winning" and only curious about the limits of flexbox and CSS grids. If you find something I can't do, that means I found a useful limit to avoid. It doesn't mean that we throw out all of flexbox and CSS grids so you can go back to the float-clear-div-class 1990s.
</p>
</rationale> </rationale>

@ -0,0 +1,95 @@
<script>
import { link } from 'svelte-spa-router';
import Icon from '../components/Icon.svelte';
import { holder } from '../../lib/imgholder.js';
import CodeView from '../components/CodeView.svelte';
let images = [1,2,3,4,5,6,7];
</script>
<style>
content {
border: 1px solid #ddd;
display: flex;
flex-direction: column;
flex: flex-grow;
padding: 1rem;
}
carousel {
outline: 2px solid green;
position: relative;
}
carousel figure {
display: none;
}
carousel figure.active {
display: flex;
position: relative;
flex-direction: column;
outline: 1px solid red;
}
carousel figure img {
width: 100%;
}
carousel figure figcaption {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 2em;
background: var(--color-bg-secondary);
opacity: 0%;
}
carousel figure figcaption:hover {
opacity: 90%;
}
carousel next,prev {
position: absolute;
bottom: 0;
opacity: 0%;
height: 100%;
display: flex;
flex-direction: column;
align-content: center;
justify-content: center;
}
carousel next {
right: 0;
}
carousel prev {
left: 0;
}
carousel next:hover,prev:hover {
opacity: 60%;
background-color: var(--color-bg);
}
</style>
<content>
<h1>Carousel</h1>
<carousel>
{#each images as image}
<figure class:active={ image === 1 }>
<img alt="Stock photo" src="{ holder(16 * 40,9 * 40) }">
<figcaption>Image #{image}</figcaption>
</figure>
{/each}
<prev><Icon name="arrow-left" size="48" /></prev>
<next><Icon name="arrow-right" size="48" /></next>
</carousel>
</content>
<CodeView source="/code/Carousel" notes="/code/Carousel.notes.html" />

@ -12,6 +12,7 @@
import Tabs from '../thumbs/Tabs.svelte'; import Tabs from '../thumbs/Tabs.svelte';
import GridOverGraphic from '../thumbs/GridOverGraphic.svelte'; import GridOverGraphic from '../thumbs/GridOverGraphic.svelte';
import Calendar from '../thumbs/Calendar.svelte'; import Calendar from '../thumbs/Calendar.svelte';
import Carousel from '../thumbs/Carousel.svelte';
import {push} from 'svelte-spa-router'; import {push} from 'svelte-spa-router';
import { holder } from '../../lib/imgholder.js'; import { holder } from '../../lib/imgholder.js';
@ -124,6 +125,11 @@
<figcaption>Calendar</figcaption> <figcaption>Calendar</figcaption>
</figure> </figure>
<figure on:click={ () => push('/demos/carousel') }>
<Carousel />
<figcaption>Carousel</figcaption>
</figure>
</images> </images>

@ -16,11 +16,14 @@ import Modal from "./demos/Modal.svelte";
import NavBar from "./demos/NavBar.svelte"; import NavBar from "./demos/NavBar.svelte";
import Tabs from "./demos/Tabs.svelte"; import Tabs from "./demos/Tabs.svelte";
import Calendar from "./demos/Calendar.svelte"; import Calendar from "./demos/Calendar.svelte";
import Carousel from "./demos/Carousel.svelte";
import GridOverGraphic from "./demos/GridOverGraphic.svelte"; import GridOverGraphic from "./demos/GridOverGraphic.svelte";
import FAQ from "./FAQ.svelte";
export default { export default {
"/": Home, "/": Home,
"/demos": Demos, "/demos": Demos,
"/faq": FAQ,
"/demos/login": Login, "/demos/login": Login,
"/demos/tiles": Tiles, "/demos/tiles": Tiles,
"/demos/modal": Modal, "/demos/modal": Modal,
@ -34,6 +37,7 @@ export default {
"/demos/navbar": NavBar, "/demos/navbar": NavBar,
"/demos/tabs": Tabs, "/demos/tabs": Tabs,
"/demos/calendar": Calendar, "/demos/calendar": Calendar,
"/demos/carousel": Carousel,
"/demos/gridovergraphic": GridOverGraphic, "/demos/gridovergraphic": GridOverGraphic,
"/demos/xoracademy": XorAcademy, "/demos/xoracademy": XorAcademy,
"/demos/xoracademy/watch": XorAcademyWatch, "/demos/xoracademy/watch": XorAcademyWatch,

@ -0,0 +1,92 @@
<script>
import Icon from '../components/Icon.svelte';
import { holder } from '../../lib/imgholder.js';
</script>
<style>
content {
border: 1px solid #ddd;
display: flex;
flex-direction: column;
flex: flex-grow;
padding: 1rem;
}
carousel {
outline: 2px solid green;
position: relative;
}
carousel figure {
display: none;
}
carousel figure.active {
display: flex;
position: relative;
flex-direction: column;
outline: 1px solid red;
}
carousel figure img {
width: 100%;
}
carousel figure figcaption {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
font-size: 2em;
background: var(--color-bg-secondary);
opacity: 0%;
}
carousel figure figcaption:hover {
opacity: 90%;
}
carousel next,prev {
position: absolute;
bottom: 0;
opacity: 0%;
height: 100%;
display: flex;
flex-direction: column;
align-content: center;
justify-content: center;
}
carousel next {
right: 0;
}
carousel prev {
left: 0;
}
carousel next:hover,prev:hover {
opacity: 60%;
background-color: var(--color-bg);
}
</style>
<content>
<h1>Carousel</h1>
<carousel>
<figure class="active">
<img alt="Stock photo" src="{ holder(16 * 40,9 * 40) }">
<figcaption>Image 1</figcaption>
</figure>
<!-- this image is not seen until set active -->
<figure>
<img alt="Stock photo" src="{ holder(16 * 40,9 * 40) }">
<figcaption>Image 2</figcaption>
</figure>
<prev><Icon name="arrow-left" size="48" /></prev>
<next><Icon name="arrow-right" size="48" /></next>
</carousel>
</content>
Loading…
Cancel
Save