<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="373326" data-post-id="373326">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>And how does the Tailwind solve that?</p>
</blockquote>
</aside>
<p>Because the styles are being specified at the element level and thus there is no need for “class name glue” to track which elements should have which styles, globally, across your entire application and org.</p>
<p>You can then compose at the <em>component</em> level instead for re-use. Components are a better unit of composition because they include the markup, styles, and even business logic and state in some frameworks. It’s better to have everything in one place.</p>
<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>And I do not find Tailwind configurable that much.</p>
</blockquote>
</aside>
<p>This is a valid criticism but “works out of the box” was the important part there.</p>
<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>And I do not know what is so bad about <code>&lt;style&gt;</code></p>
</blockquote>
</aside>
<p>The style <em>attribute</em>, not the style <em>element</em>.</p>
<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>Why? I can do stuff like <code>oklch(from red l c calc(h + 90))</code></p>
</blockquote>
</aside>
<p>Oklch is unambiguously good. I meant that it’s a stretch to say it fulfills the requirements of a design system that works out of the box (because it doesn’t fulfill that at all, actually). But it’s still good!</p>
<p>Tailwind’s colors are indeed an inferior approach, but that’s because they pre-date oklch! That is actually the point I was making, too <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>
<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>But the only reference for that scale is itself.</p>
</blockquote>
</aside>
<p><code>p-1</code> is equivalent to <code>padding: 0.25rem;</code>. It’s a scale. It’s configurable. I haven’t used Tailwind in a long time but it looks like at some point they rebuilt the whole thing on top of CSS variables or something, so idk how it works anymore.</p>
<p>The lack of a unit is historical. Tailwind is an extension of a “utility class” technique in which you create a standard set of classes (padding, font size, etc) and use those. Pre-generating classes for every imaginable unit would be far too many, so they chose a reasonable scale and stuck with that.</p>
<p>Of course nowadays there is no stripping from a set list (tree-shaking as you described); instead the compiler generates classes on the fly. You can, in fact, write <code>p-[4px]</code> if you want to.</p>
<p>I am not defending this approach, and I have been very clear that I think Tailwind’s time has come and gone. But it’s far more interesting to investigate <em>why</em> things are the way they are instead of just assuming everyone else is stupid and lazy.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373326" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/32">Post #31</a>
	                </div>
	            </div>
              <div id="likers-container-373326" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373326"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #31"></div>
  </section>
</div>
    <div class="postbit" id="373328" data-post-id="373328">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>I do not get what is the problem there. I use slots</p>
</blockquote>
</aside>
<p>The problem I’m referring to there is very specific. Remember that I was talking about CSS nesting.</p>
<p>If you have a component with scoped styles, you want to be able to compose. Like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def greeting(assigns) do
  ~H"""
  &lt;style&gt;
    .container { background-color: blue; }
    .greeting   { border: 1px solid red; }
  &lt;/style&gt;

  &lt;div class="container"&gt;
    &lt;.modal&gt;
      &lt;div class="greeting"&gt;Hello, {@name}!&lt;/div&gt;
    &lt;/.modal&gt;
  &lt;/div&gt;
  """
end
</code></pre>
<p>We want the CSS to apply to the outer <code>container</code> div, <em>and</em> the inner child <code>greeting</code> div, but <em>not</em> the elements in the <code>&lt;.modal&gt;</code> component (which are elsewhere). This property is actually very important in practice.</p>
<p>Nested CSS is not a useful compilation target for this behavior. I think you are knowledgeable enough that you can probably piece together why without me explaining it in detail. There is actually another CSS feature (the shadow dom stuff) which might work here, but I think it’s actually <em>too</em> restrictive. But that’s another conversation.</p>
<aside class="quote no-group" data-username="hauleth" data-post="27" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>I use slots and I <em>do not care</em> how it should be styled, because that is not my concern when I write <em>content</em>.</p>
</blockquote>
</aside>
<p>HTML and CSS are tightly coupled in practice. This idea that you can write each of them in isolation is a total fantasy. <em>Maybe</em> you can get away with this for something like a blog. But for apps? No.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373328" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/33">Post #32</a>
	                </div>
	            </div>
              <div id="likers-container-373328" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373328"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #32"></div>
  </section>
</div>
    <div class="postbit" id="373335" data-post-id="373335">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="hauleth" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/120/18942_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  hauleth
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="32" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Because the styles are being specified at the element level and thus there is no need for “class name glue” to track which elements should have which styles, globally, across your entire application and org.</p>
</blockquote>
</aside>
<p>Just do not use classes for stuff that do not need classes. And from my experience - classes aren’t really needed that often, as you can get pretty far with just good structure and CSS selectors that use it. For example you do not need to set classes for each single one field in form. You can set styles for <code>&lt;input&gt;</code> and go with that. If my application design change, then I do not need to go and update each single component independently, but I have it just there, in plain sight.</p>
<aside class="quote no-group" data-username="garrison" data-post="32" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>It’s better to have everything in one place.</p>
</blockquote>
</aside>
<p>At the same time I prefer to not repeat myself over and over again. With Tailwind I <em>need</em> components, because otherwise work with that codebase would be unbearable. What if, hear me out, we could style existing HTML “components” and just use them?</p>
<p>Instead of creating component like:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">  def input(assigns) do
    ~H"""
    &lt;div class="fieldset mb-2"&gt;
      &lt;label&gt;
        &lt;span :if={@label} class="label mb-1"&gt;{@label}&lt;/span&gt;
        &lt;input
          type={@type}
          name={@name}
          id={@id}
          value={Phoenix.HTML.Form.normalize_value(@type, @value)}
          class={[
            @class || "w-full input",
            @errors != [] &amp;&amp; (@error_class || "input-error")
          ]}
          {@rest}
        /&gt;
      &lt;/label&gt;
      &lt;.error :for={msg &lt;- @errors}&gt;{msg}&lt;/.error&gt;
    &lt;/div&gt;
    """
  end
</code></pre>
<p>I could just do:</p>
<pre data-code-wrap="html"><code class="lang-html">&lt;label&gt;
  Username:
  &lt;input type="text" name="username" /&gt;
&lt;/label&gt;
</code></pre>
<p>Or similar?</p>
<p>No need for fanciness, repeating stuff like <code>class="input"</code> for every single input (it is defined as such, why the hell I need to set separate class for it?).</p>
<aside class="quote no-group" data-username="garrison" data-post="32" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>The style <em>attribute</em>, not the style <em>element</em>.</p>
</blockquote>
</aside>
<p>Then for me the <strong>only</strong> advantage of Tailwind there over <code>style</code> attribute is that it allows setting some at-rules with it. Other than that it is just worse syntax for the same thing (worse, because it id full of magical names, like <code>p</code>, and with its own magical syntax, like <code>[]</code>).</p>
<aside class="quote no-group" data-username="garrison" data-post="32" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>You can, in fact, write <code>p-[4px]</code> if you want to.</p>
</blockquote>
</aside>
<p>Which requires build step from me. Which goes back to the point - how is that better than using <code>style</code> (which requires no build step) or just styling it on semantic level without any extra classes added to anything?</p>
<aside class="quote no-group" data-username="garrison" data-post="33" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>We want the CSS to apply to the outer <code>container</code> div, <em>and</em> the inner child <code>greeting</code> div, but <em>not</em> the elements in the <code>&lt;.modal&gt;</code> component (which are elsewhere). This property is actually very important in practice.</p>
</blockquote>
</aside>
<p>I never had this problem. If anything I had it other way around. So if we have component:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def foo(attributes) do
  ~H"""
  &lt;div&gt;
    &lt;style&gt;
      @scope {
        :scope { background-color: rebeccapurple }
        .greeting { color: white }
      }
      &lt;div class="greeting"&gt;Hello&lt;/div&gt;
      &lt;div class="content"&gt;{render_slot(@inner_block)}&lt;/div&gt;
  &lt;/div&gt;
  """
end
</code></pre>
<p>How to not apply <code>greeting</code> class to stuff in <code>@inner_block</code>.</p>
<p>Fortunately CSS handle that for us. With simple fix:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def foo(attributes) do
  ~H"""
  &lt;div&gt;
    &lt;style&gt;
      @scope to (.content) {
        :scope { background-color: rebeccapurple }
        .greeting { color: white }
      }
      &lt;div class="greeting"&gt;Hello&lt;/div&gt;
      &lt;div class="content"&gt;{render_slot(@inner_block)}&lt;/div&gt;
  &lt;/div&gt;
  """
end
</code></pre>
<p><a href="https://codepen.io/hauleth/pen/YPyMEXr" rel="noopener nofollow ugc">Which will now scope the styles only up to <code>.content</code> element</a>.</p>
<p>Of course with that you can also make the <code>.greeting</code> work only for the parent via simple trick:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def foo(attributes) do
  ~H"""
  &lt;div&gt;
    &lt;style&gt;
      @scope to (.content) {
        :scope { background-color: rebeccapurple }
        &amp; &gt; .greeting { color: white }
      }
      &lt;div class="greeting"&gt;Hello&lt;/div&gt;
      &lt;div class="content"&gt;{render_slot(@inner_block)}&lt;/div&gt;
  &lt;/div&gt;
  """
end
</code></pre>
<p>And now even if your code in slot will contain <code>greeting</code> class, it will not be applied there.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373335" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/34">Post #33</a>
	                </div>
	            </div>
              <div id="likers-container-373335" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373335"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #33"></div>
  </section>
</div>
    <div class="postbit" id="373336" data-post-id="373336">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="frankdugan3" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/frankdugan3/120/39210_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  frankdugan3
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>First, I feel like a few things need to be clarified about Tailwind:</p>
<ul>
<li>Tailwind prefixes however you like: <code>@import "tailwindcss" prefix(tw);</code> <code>&lt;div class="tw:flex"&gt;</code></li>
<li>As of v3, it no longer uses tree-shaking. Utilities are only added when detected being used</li>
<li>As of v4, it uses native CSS layers, so it’s very amenable to using alongside semantic CSS as a utility class library</li>
<li>As of v4, all of the utilities are based on <a href="https://tailwindcss.com/docs/theme#default-theme-variable-reference" rel="noopener nofollow ugc">native CSS variables</a>. You can add to these or selectively include what you like. This makes it very easy to leverage in semantic CSS.</li>
<li>When searching the documentation, <code>p-4</code> immediately refers to the padding section as the first result. Using a full class will be much more successful in terms of results.</li>
<li>Reverse-searching is also pretty reliable: <code>padding</code> will bring you directly to the padding section as the first result.</li>
</ul>
<p>The v4 release of Tailwind undid a lot of the weird Tailwind magic, and now it’s a small handful of directives and the rest is normal CSS. As long as you don’t use <code>@apply</code>, it’s actually very easy to migrate a project away from Tailwind simply by copying in the variables and utilities from your last build.</p>
<p>I find Tailwind convenient, if used in a more CSS-centric way than the Tailwind authors recommend. I feel the following value is provided:</p>
<ul>
<li>A standard suite of color, spacing and size variables</li>
<li>A standard suite of utility classes</li>
<li>A fast, standalone preprocessor</li>
<li>Easy customization of built-in themes, utilities, etc.</li>
</ul>
<p>The value of the above is magnified by the fact the majority of developers are already familiar with these standards.</p>
<p>I definitely agree with the distaste for piling all the utilities into the class attributes. Although that’s what’s recommended, with v4 there’s no real reason to do that just to use Tailwind. Here’s a simplified version of how I like to use Tailwind.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">def simple_form(assigns) do
  ~H"""
  &lt;form class={["core-simple-form", @class]}&gt;
    &lt;!-- ... --&gt;
  &lt;/form&gt;
  """
end
</code></pre>
<pre data-code-wrap="css"><code class="lang-css">
:root {
  // Synchronize CSS with Tailwind's dark mode -- works with any dark mode strategy
  color-scheme: light;
  @variant dark {
    color-scheme: dark;
  }
}

// Using this layer preserves full functionality of utility class overrides
@layer components {
  .core-simple-form {
    display: grid;
    padding: calc(var(--spacing) * 4);
    background: light-dark(var(--color-zinc-50), var(--color-zinc-950));
  }
}
</code></pre>
<p>As mentioned earlier, native CSS <code>@scope</code> or simply very specific selectors can easily be used to handle scoping component selectors from leaking into slots.</p>
<p>Now, I can use the generic form component in a particular place, and have the value of one-off utilities. In particular, breakpoints:</p>
<pre data-code-wrap="heex"><code class="lang-heex">&lt;.simple_form class="lg:grid-cols-2 2xl:grid-cols-3"&gt;
  &lt;fieldset class="col-span-full" field={@form[:wide]}&gt;
</code></pre>
<p>I have found this to be a very productive way to do things. The reusable components have clean CSS, and I can keep the one-off styling neatly in the component with a handfull of classes.</p>
<p>Regarding co-locating the CSS, the hooks/JS implementation uses a generic <a href="https://github.com/phoenixframework/phoenix_live_view/blob/main/lib/phoenix_component/macro_component.ex" rel="noopener nofollow ugc">MacroComponent</a>. It’s currently undocumented because I think the API and some details are still under revision. Once it’s ready for prime-time, we will be able to easily implement CSS colocation via a MacroComponent of our choosing. Personally, I don’t mind writing my classes for components in a CSS file all that much. I also don’t find much difficulty with naming component classes. Some variant of module + component name is pretty effective for namespacing in any app I’ve worked on (ERP, E-commerce, etc.) That said, a macro component can solve both of those problems in any way the developer sees fit.</p>
<p>I’m not really interested in convincing anyone whether to love/hate use/don’t use Tailwind. It’s a tool, I can work with and without it. Just sharing what I’ve found convenient and useful.</p>
<p>TLDR: We can have both semantic CSS and Tailwind, and it’s actually pretty ergonomic IMO.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373336" data-batch-url="/posts/batch_likers">
                        8
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/35">Post #34</a>
	                </div>
	            </div>
              <div id="likers-container-373336" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373336"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #34"></div>
  </section>
</div>
    <div class="postbit" id="373338" data-post-id="373338">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="hauleth" data-post="34" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>You can set styles for <code>&lt;input&gt;</code> and go with that. If my application design change, then I do not need to go and update each single component independently, but I have it just there, in plain sight.</p>
</blockquote>
</aside>
<p>This is the fantasy I’m talking about. Okay, you style your inputs globally. Putting aside that even fairly simple apps have different type of inputs, let’s think this through.</p>
<p>My inputs have errors. What do I put them in. The <code>&lt;error&gt;</code> element? Oh that’s right, there isn’t one. So now I’m doing this?</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">input + ul &gt; li { color: red; }
</code></pre>
<p>Great, now maybe somewhere in my app I try to use an input (which happens not to have errors) and a list.</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;input type="text ... /&gt;
&lt;ul&gt;&lt;li&gt;Hello, world!&lt;/li&gt;&lt;/ul&gt;
</code></pre>
<p>And now my list is red! Welcome to the Semantic Web.</p>
<p>This idea of the HTML gods defining an element for every little detail <em>did not work out</em>. It did not happen. That’s why we have components. I mean, we also now have WebComponents (sigh) but I am not opening that can of worms rn.</p>
<aside class="quote no-group" data-username="hauleth" data-post="34" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>No need for fanciness, repeating stuff like <code>class="input"</code> for every single input</p>
</blockquote>
</aside>
<p>Alright, now do <code>&lt;input class="input-totp-code" /&gt;</code>. In real apps we have more than one kind of input, and their behavior <em>transcends element boundaries</em> because there is not an element for everything!</p>
<aside class="quote no-group" data-username="hauleth" data-post="34" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>At the same time I prefer to not repeat myself over and over again. With Tailwind I <em>need</em> components, because otherwise work with that codebase would be unbearable.</p>
</blockquote>
</aside>
<p>You have reversed cause and effect. Tailwind came after everyone was <em>already</em> using components. It only makes sense in that context.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373338" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/36">Post #35</a>
	                </div>
	            </div>
              <div id="likers-container-373338" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373338"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #35"></div>
  </section>
</div>
    <div class="postbit" id="373339" data-post-id="373339">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="garrison" src="/assets/icons/user-9f439610.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  garrison
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="hauleth" data-post="34" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>How to not apply <code>greeting</code> class to stuff in <code>@inner_block</code>.</p>
</blockquote>
</aside>
<p>This is essentially the same as the problem I was describing, it’s just the simpler case. I went with the example that demonstrates the problem in both directions.</p>
<aside class="quote no-group" data-username="hauleth" data-post="34" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>Fortunately CSS handle that for us</p>
</blockquote>
</aside>
<p>Yes, <code>@scope</code> is what I was alluding to above. But there are two problems:</p>
<ol>
<li>It’s not widely available yet, so we can’t use it.</li>
<li>Afaik it scopes inherited properties like text formatting, which I have found (by experience) is the wrong behavior (inheriting formatting across scopes is actually good)</li>
</ol>
<p>A way around this is to instead use a compiler to extract the <code>&lt;style&gt;</code> contents from each component, mangle the selectors with an attribute, and inject that attribute into each element. If that sounds acceptable to you then <a href="https://git.sr.ht/~garrisonc/corp_design/tree/master/item/lib/corp_design_web/components/core_components.ex" rel="noopener nofollow ugc">we’ve reached consensus</a>.</p>
<p>And there is nothing wrong with using a compiler, btw. I’m already compiling my Phoenix apps anyway. What difference does it make if the compiler touches my CSS too?</p>
<p>What matters to me is whether the CSS looks standard for readers (i.e. in DevTools), and I’ve found the output from this approach to be quite pleasant (and certainly far better than Tailwind’s class hell).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373339" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/37">Post #36</a>
	                </div>
	            </div>
              <div id="likers-container-373339" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373339"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #36"></div>
  </section>
</div>
    <div class="postbit" id="373345" data-post-id="373345">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="frankdugan3" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/frankdugan3/120/39210_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  frankdugan3
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="37" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>Afaik it scopes inherited properties like text formatting, which I have found (by experience) is the wrong behavior (inheriting formatting across scopes is actually good)</p>
</blockquote>
</aside>
<p>I’m pretty sure you have that one backwards: it has the behavior you prefer.</p>
<blockquote>
<p><strong>Note:</strong> It is important to understand that, while <code>@scope</code> allows you to isolate the application of selectors to specific DOM subtrees, it does not completely isolate the applied styles to within those subtrees. This is most noticeable with inheritance — properties that are inherited by children (for example <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/color" rel="noopener nofollow ugc"><code>color</code></a> or <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/font-family" rel="noopener nofollow ugc"><code>font-family</code></a>) will still be inherited, beyond any set scope limit.</p>
</blockquote>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@scope" rel="noopener nofollow ugc">MDN - @scope</a></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373345" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/38">Post #37</a>
	                </div>
	            </div>
              <div id="likers-container-373345" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373345"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #37"></div>
  </section>
</div>
    <div class="postbit" id="373376" data-post-id="373376">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="hauleth" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/120/18942_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  hauleth
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="garrison" data-post="36" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>You have reversed cause and effect. Tailwind came after everyone was <em>already</em> using components. It only makes sense in that context.</p>
</blockquote>
</aside>
<p>I have not reversed it, because I never stated that. Tailwind comes as a solution to the problem that should not exist in the first place. And it doesn’t make the problem easier to avoid, it makes it even more pronounced. Again Tailwind <em>requires</em> me to use components, because otherwise the styling will fall apart pretty quickly, I never said that Tailwind is what made components popular.</p>
<aside class="quote no-group" data-username="garrison" data-post="37" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>It’s not widely available yet, so we can’t use it.</p>
</blockquote>
</aside>
<p>Pretty widely available according to <a href="https://caniuse.com/mdn-css_at-rules_scope" rel="noopener nofollow ugc">Can I Use</a>. Firefox support is lagging, but otherwise pretty broadly available.</p>
<aside class="quote no-group" data-username="garrison" data-post="37" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/g/3bc359/48.png" class="avatar"> garrison:</div>
<blockquote>
<p>A way around this is to instead use a compiler to extract the <code>&lt;style&gt;</code> contents from each component, mangle the selectors with an attribute, and inject that attribute into each element. If that sounds acceptable to you then <a href="https://git.sr.ht/~garrisonc/corp_design/tree/master/item/lib/corp_design_web/components/core_components.ex" rel="noopener nofollow ugc">we’ve reached consensus</a>.</p>
</blockquote>
</aside>
<p>For me this is still a hack, not a solution. Useful hack, but I still prefer to have my CSS separately and use semantic HTML.</p>
<p>Just for example you have <code>modal</code> component there. The question is - why, when we have <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog" rel="noopener nofollow ugc"><code>&lt;dialog&gt;</code></a> element now, that can implement such feature without all that cruft? You have <code>details</code> component, when we have <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/details" rel="noopener nofollow ugc"><code>&lt;details&gt;</code></a> that we can use. What is the point of <code>anchor</code> component when I can just style <code>&lt;a&gt;</code> element? All of that changes not only will make the codebase IMHO easier to read, but also will help with a11y, as screen readers will be able to inform the user what they are pointing at, without trying to guess from the CSS and behaviour.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373376" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/39">Post #38</a>
	                </div>
	            </div>
              <div id="likers-container-373376" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373376"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #38"></div>
  </section>
</div>
    <div class="postbit" id="373395" data-post-id="373395">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="Schultzer" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/Schultzer/120/4339_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  Schultzer
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Most developers do not understand the importance of the semantic web. And I suspect it’s because the majority of them don’t suffer a disability that would force them to use screen readers. To be honest it’s a lack of empathy that forces them to only consider what is best for them, vs having a user first perspectives.</p>
<p>Yeah it sucks that you have to learn CSS and cascading can be hard since it’s literally the opposite of what they are used to, so the path of least resistance it is.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373395" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/40">Post #39</a>
	                </div>
	            </div>
              <div id="likers-container-373395" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373395"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #39"></div>
  </section>
</div>
    <div class="postbit" id="373405" data-post-id="373405">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="derek-zhou" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/derek-zhou/120/19943_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  derek-zhou
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote no-group" data-username="hauleth" data-post="39" data-topic="72408">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/48/18942_2.png" class="avatar"> hauleth:</div>
<blockquote>
<p>Pretty widely available according to <a href="https://caniuse.com/mdn-css_at-rules_scope" rel="noopener nofollow ugc">Can I Use</a>. Firefox support is lagging, but otherwise pretty broadly available.</p>
</blockquote>
</aside>
<p>That’s a big no-no to me.</p>
<p>I do not think having <code>@scope</code> dramatically improves the situation of maintainable CSS. Nested rules will quickly go out of hand if one is not careful. Plus, we already have sass and postcss-nested for years.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="373405" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/do-you-prefer-to-use-tailwind-in-your-phoenix-projects-poll/72408/41">Post #40</a>
	                </div>
	            </div>
              <div id="likers-container-373405" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="373405"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #40"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/72408/load_more?page=5">Load more posts (10 remaining)</a>
</div></template></turbo-stream>