<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ciaran</title>
    <description>The latest articles on DEV Community by Ciaran (@slemonade).</description>
    <link>https://dev.to/slemonade</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F446740%2Ffa80c887-61c9-4ef9-bc32-5a4d1b9bbc82.jpg</url>
      <title>DEV Community: Ciaran</title>
      <link>https://dev.to/slemonade</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/slemonade"/>
    <language>en</language>
    <item>
      <title>Tailwind is Bad (If you don't know how to use it)</title>
      <dc:creator>Ciaran</dc:creator>
      <pubDate>Mon, 10 Jul 2023 21:19:52 +0000</pubDate>
      <link>https://dev.to/slemonade/tailwind-is-bad-if-you-dont-know-how-to-use-it-4g5f</link>
      <guid>https://dev.to/slemonade/tailwind-is-bad-if-you-dont-know-how-to-use-it-4g5f</guid>
      <description>&lt;p&gt;About once a year, if not more frequently, drama seems to pop up in the developer community surrounding &lt;a href="https://tailwindcss.com"&gt;Tailwind CSS&lt;/a&gt;, and it's always about the same thing: &lt;em&gt;"Look how many class names are in your markup file! So messy! How can you read any of it!?"&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's be fair - seeing a list of Tailwind classes upon first viewing can seem messy and overwhelming. CSS already has a reputation for being less-than-easy to learn, hard to memorise, and inconsistent it can be with regard to best practices.&lt;/p&gt;

&lt;p&gt;However, the recent Tailwind drama is (as usual) a great example of how a fundamental misunderstanding of tools you're using can make them seem better or worse at doing the job they're advertised to do.&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;On the left, HTML and Tailwind a dev authored with the idea it would be easier to read. &lt;br&gt;&lt;br&gt;VS. &lt;br&gt;&lt;br&gt;On the right, I rewrote the markup using vanilla CSS classes. &lt;a href="https://twitter.com/hashtag/webDev?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#webDev&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/frontEnd?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#frontEnd&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/CSS?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#CSS&lt;/a&gt; &lt;a href="https://t.co/8PoeFpccFY"&gt;pic.twitter.com/8PoeFpccFY&lt;/a&gt;&lt;/p&gt;— xirclebox (@xirclebox) &lt;a href="https://twitter.com/xirclebox/status/1673557143088242689?ref_src=twsrc%5Etfw"&gt;June 27, 2023&lt;/a&gt;
&lt;/blockquote&gt; 
&lt;h2&gt;
  
  
  The wrong end of the stick isn't always labelled
&lt;/h2&gt;

&lt;p&gt;A few days ago, &lt;a href="https://twitter.com/xirclebox"&gt;@xirclebox&lt;/a&gt; tweeted a screenshot of a side-by-side comparison between a TailwindCSS HTML snippet, and the same snippet using vanilla CSS. Currently at 2.2m views and counting, the tweet has brought opinions from just about every developer I follow, and a couple thousand more, I'm sure.&lt;/p&gt;

&lt;p&gt;There's no reason to beat around the bush here - the Tailwind snippet is much harder to read than the CSS one on two levels. First, the amount of Tailwind classes in some areas makes it really hard to get a mental model of what's going on in the snippet. Second, the amount of line breaks caused by all the classes makes it not significantly, but somewhat more challenging to read the actual HTML itself.&lt;/p&gt;

&lt;p&gt;The indentation helps, but at first glance, I do get a much better idea of the makeup of this component when looking at the vanilla CSS snippet. However, it's important to note here that OP is using &lt;a href="https://tailwindcss.com/docs/configuration#prefix"&gt;&lt;code&gt;tw-&lt;/code&gt; prefix&lt;/a&gt; (which tells us they're likely adding Tailwind to an existing code base with clashing class names), which will add 3 characters to each Tailwind class name.&lt;/p&gt;

&lt;p&gt;There's a catch though - this isn't at all how Tailwind is meant to be used.&lt;/p&gt;
&lt;h3&gt;
  
  
  Comparing Apples to Oranges
&lt;/h3&gt;

&lt;p&gt;There are two kinds of missing the point with Tailwind, generally speaking. One seems a lot more like it's up to the maintainers to attend to - which is using Tailwind for the first time, in an existing project already making use of some CSS paradigm. This is normal when working with new tools, and in some ways can be helpful to the maintainers in understanding how better to educate first-time users.&lt;/p&gt;

&lt;p&gt;On the other hand, however, we've got misrepresentation. It's impossible to say which is which, when we have no prior knowledge of the person making claims and have no idea of their exposure to Tailwind, let alone CSS itself.&lt;/p&gt;

&lt;p&gt;I think this sort of misrepresentation could be captured by turning the tables and trying to make a similar claim about CSS being too verbose compared to Tailwind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// Vanilla CSS - Messy, Unreadable, Unclear

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: #ffe7e8; border: 2px solid #e66465;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"margin: 15px; line-height: 1.5; text-align: center;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Well, I am the slime from your video&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    Oozin' along on your livin' room floor.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

// TailwindCSS - Clean, Readable, Concise

&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-orange-100 border-2 border-red-300"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"m-4 text-center leading-6"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    Well, I am the slime from your video&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    Oozin' along on your livin' room floor.
  &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But this seems misrepresentative, right? Because as much as it's possible, allowed, and even makes sense sometimes to write CSS in style tags, it's usually very impractical and the option of using external style sheets is a sound solution to this problem.&lt;/p&gt;

&lt;p&gt;One might also say, "Well, didn't you have to look up the correct Tailwind classes to use?" - No, I used intellisense in my IDE like a developer living in the modern day. Tailwind has a great plugin that allows you to hover over your classes and see the direct CSS behind it, variable patterns and all, right next to the utility class name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yi6PbVvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/byaq1xtkxb94prjrurwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yi6PbVvP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/byaq1xtkxb94prjrurwa.png" alt="TailwindCSS Intellisense Banner" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't think that @xcirclebox was intentionally misrepresenting Tailwind in the slightest. I think they're trying their best to try out a new tool that comes widely recommended - and didn't like the results. Which is honestly nothing more than a fair and free opinion, expressed well enough to engage many, many others in responding to the opinion.&lt;/p&gt;

&lt;p&gt;Let's take a look at where they may have misstepped, or where Tailwind itself isn't really clear enough to steer new users in the right direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Like Lodash, but for Styles
&lt;/h2&gt;

&lt;p&gt;To get back to basics, let's try and understand what problem Tailwind exists to solve. Let's take the &lt;a href="https://lodash.com/"&gt;lodash&lt;/a&gt; JS library for example. It's a collection of useful utility functions which, while could probably easily be written by most developers with a quick google, are a useful weapon to have in your arsenal.&lt;/p&gt;

&lt;p&gt;Sure, perhaps their &lt;code&gt;sortedLastIndexOf&lt;/code&gt; isn't the proven fastest implementation of that function in Javascript. Or, perhaps it wasn't at first - but as the project grows to become the de-facto standard for JS utility functions, it seems likely that anyone else writing a faster &lt;code&gt;sortedLastIndexOf&lt;/code&gt; will either consider contributing their solution to this massive and widely used open-source project, or let that new snippet spread and proliferate until someone notices it's a better alternative to the one lodash supplies, and likely creates a pull request correspondingly.&lt;/p&gt;

&lt;p&gt;There's something very ergonomic and useful about a collection of &lt;strong&gt;grounded&lt;/strong&gt;, &lt;strong&gt;sensible&lt;/strong&gt; and sane utilities which can be relied upon to be consistent, while still retaining opt-outs and the option to break things down a level.&lt;/p&gt;

&lt;p&gt;Bringing this metaphor back to Tailwind - we can assume that as a 6+ year old, 70k star utility CSS framework, Tailwind likely has a set of consistent and reliable utilities that shouldn't need break-outs for most projects. Their own home page refers to itself as a &lt;a href="https://tailwindcss.com"&gt;"utility-first CSS framework"&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's also worth mentioning that at this point, Tailwind serves as a great reference for how things &lt;strong&gt;should&lt;/strong&gt; be done in CSS. Their paradigms around common use cases like background images, grid / flexbox layout, and typographic styling are often implemented in a best-practices manner, and I've learned so much about CSS from hovering over my Tailwind classes and studying the underlying CSS, discovering reliable methods I return to whenever I use vanilla CSS in a project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to use TailwindCSS Properly
&lt;/h2&gt;

&lt;p&gt;There's a lot wrong with @xirclebox's Tailwind snippet, but there's some right with it too. Let's look at how it could be improved in a few ways, using the sort of best practices the Tailwind maintainers encourage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separation of Concerns in HTML and CSS
&lt;/h3&gt;

&lt;p&gt;This term is thrown around a lot when it comes to CSS and HTML. However, I don't think it makes sense to talk about HTML and CSS as 'separate concerns'. When the order of your &lt;code&gt;&amp;lt;div/&amp;gt;&lt;/code&gt;'s dictates the order in which they're &lt;strong&gt;visually displayed&lt;/strong&gt; on the page, how can we really say that the code we're using to instruct the &lt;strong&gt;layout&lt;/strong&gt; and &lt;strong&gt;visual display&lt;/strong&gt; of these elements should be hidden away in another file?&lt;/p&gt;

&lt;p&gt;Being able to glance at your component and move elements and styles around in the same actions is something we just can't do using an external CSS file. Additionally, by either omitting or including classes based on their need (rather than editing classes themselves to update appearances), we can be sure that changing the style of one element won't affect others.&lt;/p&gt;

&lt;p&gt;Say I have the following simple class for a button style:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"#fff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this style is applied to two buttons&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt; // Should be white
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt; // Should be red
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I now either need to create a whole new class, or break out into some sort of SCSS pre-processor to nest my classes in a nice, clean, BEM format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.btn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;&amp;amp;__white&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"#fff"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nt"&gt;__red&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="err"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn__white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn__red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Tailwind however, I just change the word &lt;code&gt;white&lt;/code&gt; to &lt;code&gt;red&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;// Before
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

// After
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

// 🧠 Big Brain: Set default button colour in parent
&lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;Login&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-red"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Logout&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The meaning of each class name won't be immediately obvious to a new Tailwind user, but by the time you're regularly using it across your project you'll come to appreciate reading your markup and styles in one place - leading to an almost "cleaner" result of separation of concerns. That being said, most classes are sensibly named and can be understood from name alone. Again, intellisense helps a lot here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Components
&lt;/h3&gt;

&lt;p&gt;The biggest culprit in making Tailwind look bad, is that snippets like @xirclebox's don't really represent the recommended (and common) way developers implement Tailwind.&lt;/p&gt;

&lt;p&gt;An improved version of his Tailwind snippet may look as simple as something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Carousel&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"animation-carousel"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarouselIndicator&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarouselItem&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;currentItem&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarouselButton&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;PrevIcon&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Previous&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;CarouselButton&lt;/span&gt; &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NextIcon&lt;/span&gt;&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Next&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Carousel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even simpler, just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Carousel&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"animation-carousel"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both, I'd argue, are far more readable than any of either of @xirclebox's examples.&lt;/p&gt;

&lt;p&gt;Of course, not everyone is using a framework that allows for this sort of thing. But, like it or not, that's primarily what Tailwind is made for - it was created, specifically as I understand, as a CSS utility framework &lt;em&gt;that makes sense to use with components&lt;/em&gt;, since in 2017 the options for component-friendly CSS were much more varied, and less agreed up.&lt;/p&gt;

&lt;p&gt;We still have a lot going on in our components though, right? Would our &lt;code&gt;&amp;lt;CarouselButton /&amp;gt;&lt;/code&gt; component now contain all the markup we saw in the original snippet?&lt;/p&gt;

&lt;p&gt;Good news, it won't! We've got components to rescue us again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BaseButton&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;components/BaseButton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;IconWrapper&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;components/IconWrapper&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;CarouselButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BaseButton&lt;/span&gt;
      &lt;span class="na"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"absolute top-0 left-0"&lt;/span&gt;
      &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;icon&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IconWrapper&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We did a few things here which might not be immediately obvious - let's review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We extracted shared button styles to a shared base button component.&lt;/li&gt;
&lt;li&gt;We added in only the styles required for this button &lt;strong&gt;alone&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;We prepared a wrapper component to apply styles to whichever icon we pass in.&lt;/li&gt;
&lt;li&gt;At every step, we tried to think about where we may / may not re-use styles or component fragments.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It seems obvious, but due to the current discussion maybe it's not - Tailwind covers this as a basic principle in their &lt;a href="https://tailwindcss.com/docs/reusing-styles"&gt;TailwindCSS Core Concepts&lt;/a&gt; documentation. It's worth a read if you find yourself repeating styles, even as an experienced Tailwind user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Downsides, and Back-and-Forth of TailwindCSS
&lt;/h3&gt;

&lt;p&gt;As much as the examples above seem like a great improvement on the original snippets, there's still the issue of having separate styles in separate files - although this time, with their related markup and at times, content. Speaking from experience, however, this is a very reasonable alternative to having to view &lt;em&gt;entire&lt;/em&gt; groups of markup and styling separately.&lt;/p&gt;

&lt;p&gt;When I want to change something about a &lt;code&gt;&amp;lt;CarouselButton/&amp;gt;&lt;/code&gt;, I'm entering that file prepared to edit the markup, styles, and possibly JS that affects either of those, aware that &lt;em&gt;my power is now limited to the button&lt;/em&gt;. Consequently, I'm then editing the &lt;code&gt;&amp;lt;Carousel/&amp;gt;&lt;/code&gt; itself, which isn't much more than a layout wrapper, to make sure that my new button styles don't mess up my existing layout.&lt;/p&gt;

&lt;p&gt;This practice, when done with intention and specificity, grows into a larger skill of defining re-usable components by default. Small notions like "padding should be applied from a parent, not from within a child", and asking yourself "do I want to pass just the text, or the text tag too?" make a big difference in designing components that &lt;em&gt;just work&lt;/em&gt; when re-used across a code base - a principle which Tailwind prioritises over first being easy-on-the-eyes.&lt;/p&gt;

&lt;p&gt;Again, there's always the opportunity for extra rules, abstraction componentized and one-offs in your &lt;code&gt;globals.css&lt;/code&gt; or &lt;code&gt;tailwind.config.js&lt;/code&gt; files - but again to speak from experience, if either of these files is hitting more than 100 lines, it's incredibly likely you're missing a key instruction from the docs, and making your own life more difficult needlessly.&lt;/p&gt;

&lt;p&gt;At the end of the day, this is largely down to personal preference - but I strongly it's a personal preference between two &lt;em&gt;ideal&lt;/em&gt; options - rather than a good implementation of one option, and a weak implementation of another. To go back to the lodash example, no one wants to use my one-liner &lt;code&gt;sortedLastIndexOf&lt;/code&gt; that's slower and always requires a review of usage due to lack of documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Conclusion
&lt;/h2&gt;

&lt;p&gt;In general, I don't think it's a great example of how usable Tailwind is to post large HTML snippets with a multiple components in a row. It's almost never used this way, and the way in which it &lt;em&gt;is&lt;/em&gt; used is a lot more malleable and customizable than it first appears &lt;em&gt;without altering any of the library's defaults&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A good process to follow when Tailwind starts to become unreadable is to ask how the styles can be broken down and, more specifically, componentised - intrinsically tied to the components they're responsible for displaying.&lt;/p&gt;

&lt;p&gt;Hopefully this discussion, as they always seem to, brings some wider awareness of how folks are using Tailwind in ways that aren't ideal. At the least, previous such drama has done so for me - especially around the usage of @apply...&lt;/p&gt;



&lt;blockquote&gt;
&lt;br&gt;
&lt;p&gt;nothing i am trying my best&lt;/p&gt;— Apply (@Apply) &lt;a href="https://twitter.com/Apply/status/1673883517036662784?ref_src=twsrc%5Etfw"&gt;June 28, 2023&lt;/a&gt;&lt;br&gt;
&lt;/blockquote&gt; 

</description>
      <category>tailwindcss</category>
      <category>css</category>
      <category>frontend</category>
      <category>productivity</category>
    </item>
    <item>
      <title>ERC-20, ERC-721, and other Smart Contract Standards Explained</title>
      <dc:creator>Ciaran</dc:creator>
      <pubDate>Fri, 17 Sep 2021 11:31:27 +0000</pubDate>
      <link>https://dev.to/slemonade/an-overview-of-the-most-popular-smart-contract-standards-35fj</link>
      <guid>https://dev.to/slemonade/an-overview-of-the-most-popular-smart-contract-standards-35fj</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;I recently wrote on article on &lt;a href="https://ciaran.co.za"&gt;my website&lt;/a&gt; covering the basics of Ethereum-based DeFi Applications for web Developers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a snippet on tokens which was the one of the key things I was attempting ti summarize well. If you enjoy this piece, please check out the full article on my website!&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Most Popular Ethereum Smart Contract Standards (ERC-20, ERC-721, ERC-777, ERC-1155)
&lt;/h2&gt;

&lt;p&gt;ERC (Ethereum Request for Comment) Token interface standards make smart contracts composeable. This means they will stay compatible despite changes to decentralized exchanges. Each standard defines a specific combination of 'rules' that a token must adhere to. There is a really great article &lt;a href="https://ethereum.org/en/developers/tutorials/understand-the-erc-20-token-smart-contract/"&gt;covering ERC-20 makeup interaction basics&lt;/a&gt; - ERC-20 is the most common (and possibly simple) standard, and is best explored first.&lt;/p&gt;

&lt;p&gt;Each smart contract has a set of mandatory functions - for example, an ERC-20 token has: &lt;code&gt;totalSupply&lt;/code&gt;, &lt;code&gt;balanceOfWallet&lt;/code&gt;, &lt;code&gt;transferFrom&lt;/code&gt;, and more. We also use the smart contract to store functions for handling transactions and balances.&lt;/p&gt;

&lt;p&gt;I want to cover a few of the basics of the tokens you will most commonly encounter. By no means are these comprehensive descriptions - they're simply a catch-up, to help you get comfortable with the terminology (and application), just enough so that you can start exploring interesting smart contracts that other people have written.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;a href="https://eips.ethereum.org/"&gt;Ethereum Improvements Proposals Website&lt;/a&gt; is the central location for platform, api and contract standard proposals. It's a cool place to look around once you've got some basic understanding of the more popular ERC standards.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ERC-20
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://tokenmint.io/blog/mintable-erc20-token-explained.html"&gt;The Standard Fungible Token Interface&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the most common, and what is considered the 'base standard'. Most ETH based tokens you'll encounter are ERC-20 Tokens. These can be used for purposes such as managing voting or currency systems - where fungiblity is important. An ERC-20 Token can also be used to create, as mentioned, a cryptocurrency on the Ethereum blockchain.  &lt;/p&gt;

&lt;p&gt;A great place to start if you want to write ERC-20 contracts is this tutorial which covers &lt;a href="https://www.quicknode.com/guides/solidity/how-to-create-and-deploy-an-erc20-token"&gt;creating an ERC-20 token on Ropsten Test Net&lt;/a&gt;. I used this tutorial to create &lt;a href="https://ropsten.etherscan.io/token/0x422b16d7f90bd9d732fbe7c6cfddb50e0d38c606"&gt;&lt;code&gt;$lemToken&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While the other tokens in this aticle have documentation pages linked in this article, if you're going to read just one of the standards I would recommend ERC-20. It's what most other smart contract standards are modelled after in one way or another - &lt;a href="https://docs.openzeppelin.com/contracts/3.x/erc20"&gt;&lt;strong&gt;The ERC-20 Standard&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC-721
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://medium.com/geekculture/mint-an-nft-and-erc-721-smart-contract-easy-step-by-step-4fafff151fbe"&gt;The Standard Non-Fungible Token Interface&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A &lt;code&gt;721&lt;/code&gt; is non-fungible (ie. it has a no 1:1 value). I saw it referred to as a "deed" which made the most sense to me personally. While the standard has many feautures it shares with ERC-20, it's got a unique &lt;code&gt;tokenId&lt;/code&gt; field - which adds its infamous functionality of being a uniquely identifiably token. &lt;/p&gt;

&lt;p&gt;There's some further discussion around how the "art itself" that you might mint as an NFT appears in the NFT itself as, essentially, a link to an off-chain copy of the resource - but this has some pretty practical reasons for it. &lt;/p&gt;

&lt;p&gt;Once you have a decent understanding of how ERC-20 works (and have perhaps tried to create your own), I'd highly recommend doing the &lt;a href="https://medium.com/rarible-dao/how-to-mint-a-10-000-item-generative-art-nft-collection-with-21-lines-of-javascript-dfa603cc56d5"&gt;tutorial on minting a 10,000 piece unique art collection&lt;/a&gt;. It glosses over the finer details of smart contracts, but is one of the best catch up articles on the NFT space that I've found. &lt;/p&gt;

&lt;p&gt;For a little extra research, it's important looking into &lt;a href="https://ipfs.io/#why"&gt;ipfs&lt;/a&gt;, which is a distributed web concept most often employed for storing the actual "asset" part of digial art on the blockchain. This is one of the core components of working with dApps - it's unavoidable at this point.&lt;/p&gt;

&lt;h3&gt;
  
  
  ERC-777
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://docs.openzeppelin.com/contracts/3.x/erc777"&gt;Non-Standard Fungible Token&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Triple-seven is a fungible token standard, which attempts to add functionality to what would otherwise be similar to an ERC-20. Essentially, it's for building tokens with complex functionality. I would recommend this &lt;a href="https://www.youtube.com/watch?v=CVdZ09iqQj8"&gt;Jordi Baylina talk on ERC-777 from DappCon&lt;/a&gt; as an introduction (once you've read the docs, of course).&lt;/p&gt;

&lt;p&gt;The key feature of ERC-777 is &lt;strong&gt;receive hooks&lt;/strong&gt;, which is a type of function that can be called when tokens are sent to it. As a web developer, the general goal of React Hooks is a good comparison here - &lt;em&gt;hooks attempt to make it easier to control the flow of a complex set of actions&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By this point, you've probably realised that most popular smart contract technology is made up of not one, but rather a network of contracts. This is an important concept to grasp, in order to understand the boundaries of immuatability and malleability of the network.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  ERC-1155
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.openzeppelin.com/contracts/3.x/erc1155"&gt;An Attempt at a Fungibility-Agnostic Token&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ERC-1155 is a standard combining efforts of all the contracts we've explored so far, creating a way to write contracts that manage multiple token types. Within a single contract, we can work with fungible, non-fungible, and almost any other sort of token in between. It does all of this while attempting to be even more efficient and cheap to work with than other smart contract standards.&lt;/p&gt;

&lt;p&gt;It has a massive difference in gas fees (which we'll get to next) compared to other token standards, and you'll most often see it used in applications like dApp Games. These sorts of applications have the most cause to use a cheap and malleable method of managing a complex internal token system.&lt;/p&gt;

&lt;p&gt;ERC-1155 is sometimes referred to as the &lt;em&gt;lazy minting&lt;/em&gt; standard - it's the cheapest, most functional and most approachable for newcomers. Whether or not the implications of the "lazy" label fit remains to be seen, however no such label should never discourage you from exploring.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>erc20</category>
      <category>defi</category>
      <category>web3</category>
    </item>
    <item>
      <title>10 CSS Tips &amp; Tricks for Beginners</title>
      <dc:creator>Ciaran</dc:creator>
      <pubDate>Mon, 23 Nov 2020 14:03:35 +0000</pubDate>
      <link>https://dev.to/slemonade/10-css-tips-tricks-for-beginners-3ed3</link>
      <guid>https://dev.to/slemonade/10-css-tips-tricks-for-beginners-3ed3</guid>
      <description>&lt;p&gt;CSS tips and tricks are invaluable as a web designer, as it is the single most important tool used in designing websites. It's used to add styles to HTML web pages and is often used alongside Javascript. If you've spent any amount of time learning web design, you've undoubtedly encountered it.&lt;/p&gt;

&lt;p&gt;As with any of the core components of web development (HTML, CSS, and JS), there are many practices, shortcuts, and 'secrets' that aren't often so easy to learn. It's important to grasp these concepts well early on so that you don't spend hours trying to center a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; every time you try and create something new.&lt;/p&gt;

&lt;p&gt;Let's take a look at some of these CSS tips and tricks, and try to help you nail down the bare essentials to help build a solid knowledge of the tool. &lt;/p&gt;

&lt;h2&gt;
  
  
  Ten CSS Questions and Answers for Newbies
&lt;/h2&gt;

&lt;p&gt;Here are ten questions (and their answers) which I think would have boosted my learning when first starting with CSS. Some of them are simple, and others are a little more complex to get your head around, but there's something in this guide for everyone. Let's dig in.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does CSS Stand For?
&lt;/h3&gt;

&lt;p&gt;CSS stands for Cascading Style Sheets. It's named as such as it is a language used to style web pages written in &lt;a href="https://www.w3schools.com/xml/xml_whatis.asp"&gt;HTML and XML&lt;/a&gt;. CSS can be written either directly within the HTML markup or saved as an external &lt;code&gt;.css&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;In modern web development, skills in CSS are often expected to extend into stylesheet-based frameworks such as SCSS and Sass, Bootstrap, and &lt;a href="https://ciaran.co.za/tailwind-css-wordpress-theme-tutorial/"&gt;TailwindCSS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to add CSS to HTML
&lt;/h3&gt;

&lt;p&gt;There are three ways to add CSS to HTML: Inline, Internal and External styles. Let's add some CSS to give a web page a blue background, seeing how it's done using each method. &lt;/p&gt;

&lt;p&gt;Internal CSS refers to styles written within the head tags of a web page. You can use internal CSS as you see in the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;head&amp;gt;
...
&amp;lt;style&amp;gt;
    body {
        background-color: blue;
    }
&amp;lt;/style&amp;gt;
...
&amp;lt;/head&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, is external CSS - the most common way to use it in modern web development. With external CSS, we store our CSS in an external .css file, adding a link to it in the head of the HTML document. In this case, our &lt;code&gt;style.css&lt;/code&gt; might look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;body {
        background-color: blue;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the head of our HTML document we would point to the style sheet with a link tag as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link rel="stylesheet" href="style.css"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, with inline CSS, we use the style property of HTML tags to apply styles to each element individually. The same example in inline CSS would appear like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;body style="background-color: blue;"&amp;gt;
...
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, while in this case, it might seem inline styles are quickest, they become near useless when repeating elements. Besides, it's best practice to keep as many of our resources separate as possible when designing websites, in the case they should grow large and difficult to maintain.&lt;/p&gt;

&lt;p&gt;As such, external CSS is the de facto standard - it allows you to keep your style sheets external and organised (and keeps your HTML clean and easy to read). What's more, with frameworks like SCSS / Sass, you can split your style sheets into files organised for different sections of your site, or different design components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P6dyjuuk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/lee-campbell-DtDlVpy-vvQ-unsplash.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P6dyjuuk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/lee-campbell-DtDlVpy-vvQ-unsplash.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Center Text in CSS
&lt;/h3&gt;

&lt;p&gt;The simplest way to center-align text CSS is to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text-align: center;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this only centers relative to the parent element - so if your text is in a div which takes up 50% of the page, then it will be centered at 25% of the total page width. This is one of those cases where over time, you'll understand better how this works by applying it again and again, in different circumstances.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Center an Image in CSS
&lt;/h3&gt;

&lt;p&gt;Centering an image in CSS is pretty simple. If we add an image with the center-image class applied, we can add the following CSS to center the element within its parent element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.center-image {
    display: block;
    margin-left: auto;
    margin-right: auto;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also reduce the image width if the image is larger than the web page itself. The same margin principle can be used with most other elements to center them on a webpage. To understand more about this, you should &lt;a href="https://css-tricks.com/snippets/css/a-guide-to-flexbox/"&gt;read up on flexbox&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Change Text Colour in CSS
&lt;/h3&gt;

&lt;p&gt;This is a quick and simple one. While you might be looking for a &lt;code&gt;text-color&lt;/code&gt; value or something similar, it's far more simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p {
        color: red;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I find it's best to think of colour in CSS as split into foreground and background - with the former as the above, and the latter as &lt;code&gt;background-color&lt;/code&gt;. In CSS, the text takes on the foreground colour you've for itself, otherwise its parent element.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Comment in CSS
&lt;/h3&gt;

&lt;p&gt;To add a comment in CSS, simply add two forward slashes with two stars in between them, and your comments in the middle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/* this is a comment */
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commenting is a very important consideration when writing clean code. When you refer back to your code for tweaking or maintenance, you might not always remember what you were thinking when you wrote it. As such, comments make this a more seamless process - especially in the case where other developers have to refer to code you've written or vice versa. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to Change Font in CSS
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--st0T5N4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/brett-jordan-B_j4LJbam5U-unsplash.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--st0T5N4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/brett-jordan-B_j4LJbam5U-unsplash.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Changing from the default fonts in CSS is probably in the three first things designers do in creating a new web page. In addition, many will specify different body, and heading fonts (if not a few more for other distinct copy elements). &lt;/p&gt;

&lt;p&gt;To specify, for example, a body and heading font, you can use the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1, h2, h3 {
    font-family: Arial;
}

p {
    font-family: Karla;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if we wanted to use a font like Karla (used on this site), which is hosted on Google fonts, we need to ensure that website visitors can access this font. We can easily do this by adding the &lt;a href="http://fonts.google.com/"&gt;link provided by Google Fonts&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;link href="https://fonts.googleapis.com/css2?family=Karla&amp;amp;display=swap" rel="stylesheet"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most font services like Google Fonts also allow you to select only the weights and styles (italic, bold, etc) that you use on your site, to minimize the size of the files a user downloads when visiting the site. &lt;/p&gt;

&lt;h3&gt;
  
  
  How to Remove Underline from Link CSS
&lt;/h3&gt;

&lt;p&gt;By default, HTML links or anchor elements look really, really bad. Blue, underlined, and straight off your grandparents' computer from the 90s. To reset styling on link elements, we need to start with the following snippet of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a {
    text-decoration: none;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will remove the underline from links. We can then simply change the colour of the link to something we prefer - something different from your paragraph font colour is best, as differentiating links in text helps with accessibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a {
    text-decoration: none;
    color: palegreen;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we can add styles to links that change depending on whether the link has been visited or not. Similarly, this applies to hovered links (this principle works for all elements), and active (clicked) links:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a {
    text-decoration: none;
    color: palegreen;
}

a:hover {
    text-decoration: underline;
    color: blue;
}

a:visited {
    color: red;
}

a:active {
    color: green;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How to Add a Background Image in CSS
&lt;/h3&gt;

&lt;p&gt;Adding background images in CSS is a great way to manage responsive images, as individual &lt;code&gt;img&lt;/code&gt; elements can become finicky when used within other elements on responsive web pages. To add a background image to a div with the class of &lt;code&gt;bg&lt;/code&gt;, you can use the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.bg {
    width: 100vw;
    height: 100vh;
    background-image: url(https://images.unsplash.com/photo-1571319791337-3d18ca429a6c);
    background-position: center;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;background-position&lt;/code&gt; set to &lt;code&gt;center&lt;/code&gt; the image will, by default, attach itself using the top right corner. In addition, you might have noticed I set the width and height of the div using strange values. More on that in the next point.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is VH and VW in CSS
&lt;/h3&gt;

&lt;p&gt;VW and VH stand for viewport width and viewport height. These refer to sizes of the actual device the user is viewing the website on, and not simply pixel measurements. It breaks up the viewport height and width into a percentage factor, with &lt;code&gt;100vw&lt;/code&gt; representing 100% of the viewport width. &lt;/p&gt;

&lt;p&gt;A common usage of this might be using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;section {
    height: 100vh;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the hero section of a web page, so that it covers the entire user screen on both mobile and desktop.&lt;/p&gt;

&lt;p&gt;Remember, however, that it's the entire height and width of the user's device - so on web browsers, this &lt;strong&gt;includes&lt;/strong&gt; the space used by the toolbars et cetera at the top of your screen. &lt;/p&gt;

&lt;h2&gt;
  
  
  Some Notes for CSS Beginners: Where to Go Next
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Pql1xLh5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/Screenshot_2020-11-23-Sass-Sass-Basics.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Pql1xLh5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.ciaran.co.za/wp-content/uploads/2020/11/Screenshot_2020-11-23-Sass-Sass-Basics.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you're feeling established in CSS, I would highly recommend swiftly moving onto SCSS / Sass. These are Javascript-aided CSS tools, which allow you to do more complex things in CSS, while also allowing most of your plain-written CSS to still be valid. For example, targeting paragraphs &lt;em&gt;only&lt;/em&gt; within a certain element is simple, without assigning that element a class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.hero {
    color: red;
    p {
        color: blue;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While you're at it, check out frameworks like Bootstrap and TailwindCSS - while they offer a different skill set and have their learning curve, you can often learn a lot about CSS in how these frameworks are used and structured. It's a two-way deal.&lt;/p&gt;

</description>
      <category>css</category>
      <category>beginners</category>
      <category>design</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to Create a Tailwind CSS + WordPress Theme Boilerplate</title>
      <dc:creator>Ciaran</dc:creator>
      <pubDate>Mon, 28 Sep 2020 14:56:40 +0000</pubDate>
      <link>https://dev.to/slemonade/how-to-create-a-tailwind-css-wordpress-theme-boilerplate-2g6</link>
      <guid>https://dev.to/slemonade/how-to-create-a-tailwind-css-wordpress-theme-boilerplate-2g6</guid>
      <description>&lt;p&gt;A few months ago, when I was first getting started with &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Adam Wathan’s TailwindCSS&lt;/a&gt;, I was really put off by how hard I was finding it to install as a part of various frameworks. As such, I decided to put this guide together to demonstrate how to scaffold an efficient TailwindCSS + WordPress development setup. &lt;/p&gt;

&lt;p&gt;In this guide we’ll go through the pros and cons of using TailwindCSS with WordPress, how to quickly set up a template that I created (so you don’t have to install anything yourself), and how to create a blank theme from scratch which uses Tailwind. &lt;/p&gt;

&lt;p&gt;If you have any questions or recommendations, don’t hesitate to tweet me &lt;a href="https://twitter.com/parabyl" rel="noopener noreferrer"&gt;@parabyl&lt;/a&gt;! I’m always keen to get second opinions on what I’m doing, and feedback on the &lt;a href="https://ciaran.co.za/projects/" rel="noopener noreferrer"&gt;projects I’m working on&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Jump to: Quick Setup&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use TailwindCSS with WordPress
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FHrsz21v_junJ1ixS-ilGZlRR1XEfHu4uRrr77wchgB5El7SrFFBRFl5CKByQdywrZ1SBbyi9d7nC3b-lzPy0bh_ru7vYHRXBvUaWBqezh-VWae1W_St9H8VrZ6nf2uHd6u2R_bsL" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FHrsz21v_junJ1ixS-ilGZlRR1XEfHu4uRrr77wchgB5El7SrFFBRFl5CKByQdywrZ1SBbyi9d7nC3b-lzPy0bh_ru7vYHRXBvUaWBqezh-VWae1W_St9H8VrZ6nf2uHd6u2R_bsL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on what you regard as best practices, you might think using a utility-based CSS framework with WordPress a bit confusing – aren’t we meant to be keeping our HTML clean and readable? &lt;/p&gt;

&lt;p&gt;Well, it turns out that Tailwind offers some gains where my previous setup of WordPress + Elementor + A Solid Theme was giving me issues. Let’s explore a few of these areas in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 4 Benefits of TailwindCSS for Theme Development
&lt;/h3&gt;

&lt;p&gt;There are four standout benefits that I see using TailwindCSS, specifically for theme development, compared to other frameworks. These are all pros that any self-respecting designer should at least understand, if not agree with.&lt;/p&gt;

&lt;h4&gt;
  
  
  Theming Capabilities
&lt;/h4&gt;

&lt;p&gt;Theming is important to you, if you’re reading this. It’s a practice that allows us to define common styles across an entire project, allowing for brand identity and visual hierarchy to shine through as it should. Tailwind’s &lt;code&gt;tailwind.config.js&lt;/code&gt; file allows us to set up parameters such as fonts, colours, and utilities, as well as allowing us to overwrite the default Tailwind styles. &lt;/p&gt;

&lt;p&gt;This way, if we wanted to expand our project into a new realm (say, launching a product under the same company name), we could simply copy over the &lt;code&gt;tailwind.config.js&lt;/code&gt; file to the new project, using the exact same base CSS setup. &lt;/p&gt;

&lt;h4&gt;
  
  
  Performance Optimization
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FuYlJXVM2r5neMwCLJ9_YEriXafWMTriTsWpQBBDwwX2SV_hNxga9g9y5YXxfzbkkiITle6TID2gENbjRkQgV8wtCG3yp5jQyKf0rmr9i8PUlz-gi6WQ8j2WGryy_Ysj-IZH-abt8" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FuYlJXVM2r5neMwCLJ9_YEriXafWMTriTsWpQBBDwwX2SV_hNxga9g9y5YXxfzbkkiITle6TID2gENbjRkQgV8wtCG3yp5jQyKf0rmr9i8PUlz-gi6WQ8j2WGryy_Ysj-IZH-abt8"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TailwindCSS (as of version 1.8) is just under 200kb Gzipped. This is small, however if we take the stylesheet for this website, it’s just under 15kb (&lt;strong&gt;TINY!&lt;/strong&gt;). &lt;/p&gt;

&lt;p&gt;This is thanks to Tailwind using PurgeCSS – a module which mixes CSS classes you &lt;em&gt;actually&lt;/em&gt; used into your output files. Didn’t use &lt;code&gt;max-w-lg&lt;/code&gt;? It won’t exist in your output style.css.&lt;/p&gt;

&lt;h4&gt;
  
  
  Readability
&lt;/h4&gt;

&lt;p&gt;One of my favourite parts of TailwindCSS is how readable it is, once you get to grips with the lexicon of the framework. To be able to dip into a WordPress theme and see styling, logic, and markup all neatly positioned together is a major pro. &lt;/p&gt;

&lt;p&gt;Further, when you combine the addition of Tailwind CSS classes with conditional logic in your .php files, you’re on your way to building some really cool state or logic-responsive components in your theme. &lt;/p&gt;

&lt;h4&gt;
  
  
  The TailwindCSS Community
&lt;/h4&gt;

&lt;p&gt;Being a large and popular growing framework, there are so many resources out there for Tailwind – from live websites, to examples and tutorials, and even &lt;a href="https://mertjf.github.io/tailblocks/" rel="noopener noreferrer"&gt;free component libraries&lt;/a&gt; for you to use. This is one of the biggest advantages of using a framework which is rapidly growing in popularity, as it means when you run into an issue, someone else has likely found a solution. &lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start: HTML5Blank + TailwindCSS Template
&lt;/h2&gt;

&lt;p&gt;So, all that intro aside, let’s begin with the template I created. I’ll teach you to set a theme up from scratch with Tailwind further down in this tutorial, however for now let’s just explore the simple setup option.&lt;/p&gt;

&lt;p&gt;You can &lt;a href="https://github.com/knightspore/wordpress-tailwind/archive/master.zip" rel="noopener noreferrer"&gt;download the template here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theme Installation &amp;amp; Setup
&lt;/h3&gt;

&lt;p&gt;First, &lt;a href="https://github.com/knightspore/wordpress-tailwind" rel="noopener noreferrer"&gt;clone the repo I published&lt;/a&gt; as a starter. It’s based on &lt;a href="http://html5blank.com/" rel="noopener noreferrer"&gt;HTML5Blank&lt;/a&gt; as this is one of the best blank themes you can use for learning theme development. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/knightspore/wordpress-tailwind.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, you’ll need to install dependencies using your preferred package manager&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save-dev
or
yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you’re ready to start using the theme! Run &lt;code&gt;npm run dev&lt;/code&gt; or &lt;code&gt;yarn dev&lt;/code&gt; to compile your assets unminified, &lt;code&gt;watch&lt;/code&gt; to re-compile theme every time you save, or &lt;code&gt;prod&lt;/code&gt; to run your production build. &lt;/p&gt;

&lt;p&gt;You can edit &lt;code&gt;assets/style.css&lt;/code&gt; to edit your CSS (for &lt;a class="mentioned-user" href="https://dev.to/apply"&gt;@apply&lt;/a&gt; and non-inline styles), and &lt;code&gt;assets/main.js&lt;/code&gt; to edit your Javascript. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a WordPress Theme using TailwindCSS
&lt;/h2&gt;

&lt;p&gt;Now that you’ve got the option of quick setup, let’s run over an installation on a blank WordPress theme in case you don’t want to use HTML5Blank. &lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up your Theme
&lt;/h3&gt;

&lt;p&gt;To begin, let’s navigate to &lt;code&gt;wp-content/themes&lt;/code&gt; and run &lt;code&gt;mkdir example&lt;/code&gt; (where ‘example’ is your theme name). In order for WordPress to recognize this folder as a theme, we need to add a few items.&lt;/p&gt;

&lt;p&gt;Let’s open the folder and run &lt;code&gt;touch style.css index.php&lt;/code&gt;. You should now see these two files appear, and be able to use the blank theme in Appearance &amp;gt; Themes in your WordPress Admin dashboard. Let’s also run &lt;code&gt;touch header.php footer.php&lt;/code&gt; as we’ll need these later. &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing Laravel Mix
&lt;/h3&gt;

&lt;p&gt;Next, we need to install Laravel mix. This is the cleanest wrapper for webpack that I’ve found, and it works really nicely for wordpress theme development as a lot of the confusing syntax has been removed. &lt;/p&gt;

&lt;p&gt;First, run &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install laravel-mix cross-env --save-dev 
or 
yarn add laravel-mix cross-env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cp node_modules/laravel-mix/setup/webpack.mix.js ./
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You should now see a &lt;code&gt;node_modules/&lt;/code&gt; directory, as well as &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;webpack.mix.js&lt;/code&gt; files in your root directory. &lt;/p&gt;

&lt;p&gt;If we look inside our Laravel Mix Config file, we can see a simple setup has been scaffolded. It’s taking assets from a folder called &lt;code&gt;src/&lt;/code&gt; and compiling them into a folder called &lt;code&gt;dist/&lt;/code&gt;. To complete our setup of mix, we need to create the source assets that mix is looking for. &lt;/p&gt;

&lt;p&gt;Run&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir src; touch src/app.js src/app.css
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;(Note: we’re using CSS instead of SASS here as Tailwind does not require pre-processors)&lt;/p&gt;

&lt;p&gt;Finally, copy and paste the &lt;a href="https://laravel-mix.com/docs/5.0/installation" rel="noopener noreferrer"&gt;recommended Laravel Mix Build Scripts&lt;/a&gt; into &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"scripts": {
    "dev": "npm run development",
    "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
    "watch": "npm run development -- --watch",
    "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
    "prod": "npm run production",
    "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Installing TailwindCSS
&lt;/h2&gt;

&lt;p&gt;To install Tailwind, let’s begin by adding it with our package manager&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add tailwindcss
or
npm install tailwindcss --save-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, add the TailwindCSS directives to your &lt;code&gt;src/app.css&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, we need to update &lt;code&gt;webpack.mix.js&lt;/code&gt; to build assets correctly. As with most of these code snippets, the TailwindCSS installation page has got us covered once again: replace the file contents with the following.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let mix = require('laravel-mix');

mix.js('src/app.js', 'js/app.js')
    .postCss('src/app.css', 'style.css', [
        require('tailwindcss'),
        require('autoprefixer'),
      ]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Generate a blank config file using &lt;code&gt;npx tailwindcss init&lt;/code&gt; (you’ll want this file later) and we’re ready to go! &lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your Assets with Laravel Mix
&lt;/h2&gt;

&lt;p&gt;To test our build, run &lt;code&gt;npm run dev&lt;/code&gt; or &lt;code&gt;yarn dev&lt;/code&gt;. You should see some confirmation from your package manager upon running this command. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fghh4PM9DIutNb6HlH87VTbtnCPG31fwg9T78pB6fhjQOBCvmRBsSZAh5mZMXZpSPy78_rwU_q-J0l2SrSPcph3hYFlBSQexEq92fIxqiOfTdG4sV19seeHs1wp-Nh8n6ywmt-EDn" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fghh4PM9DIutNb6HlH87VTbtnCPG31fwg9T78pB6fhjQOBCvmRBsSZAh5mZMXZpSPy78_rwU_q-J0l2SrSPcph3hYFlBSQexEq92fIxqiOfTdG4sV19seeHs1wp-Nh8n6ywmt-EDn"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s try adding some basic HTML to our index.php to see if Tailwind is working properly. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;h1 class=”text-xl text-red-500”&amp;gt;Hello World&amp;lt;/H1&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can run your watch script at this point if you’re working with your &lt;code&gt;src/app.css&lt;/code&gt; file instead of inline styles.  &lt;/p&gt;

&lt;p&gt;If you’ve followed correctly, the styling on your H1 &lt;em&gt;should not&lt;/em&gt; work immediately. We first need to add the &lt;code&gt;wp_head()&lt;/code&gt; directive to our header. This will add references such as our stylesheet into the &lt;/p&gt; of our theme. 

&lt;p&gt;To do this, let’s first generate a simple HTML setup in our header.php and add our header directive to it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;?php wp_head(); ?&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;

&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From here, we can cut the last two lines and paste them into our footer.php file. Next, let’s include our header and footer in our index.php file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php get_header(); ?&amp;gt;
&amp;lt;h1 class="text-xl text-center text-red-500"&amp;gt;Hello World&amp;lt;/h1&amp;gt;
&amp;lt;?php get_footer(); ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And finally, we need to enqueue our stylesheet by creating &lt;code&gt;functions.php&lt;/code&gt; and adding the following&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php
wp_enqueue_style('style', get_stylesheet_uri());
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, when you refresh your site, you should see your inline styles showing. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Foq-8MAheO2y14jXTkKD25qnQnbmPjTRwxpKo0MxgvozzGunhbTQmbGoOyyAlZRaSsDM_uObPicnpLztO2uas5aDHtjKyOkOEa-rTDT6SOKe_iaIe75XiFMJ2qVFM6wvEoiZv-iC_" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Foq-8MAheO2y14jXTkKD25qnQnbmPjTRwxpKo0MxgvozzGunhbTQmbGoOyyAlZRaSsDM_uObPicnpLztO2uas5aDHtjKyOkOEa-rTDT6SOKe_iaIe75XiFMJ2qVFM6wvEoiZv-iC_"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Controlling TailwindCSS File Size
&lt;/h3&gt;

&lt;p&gt;Now, you might have noticed that when we compiled our styles, our output CSS was a whopping 2.28mb. This is because, by default, Tailwind includes all its possible utilities in our output file. &lt;/p&gt;

&lt;p&gt;Luckily, as I mentioned earlier, Tailwind uses PurgeCSS to easily remove unused classes from our output. We just need to update the purge section of our &lt;code&gt;tailwind.config.js&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;purge: [
    './**/*.php',
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, when we run &lt;code&gt;yarn prod&lt;/code&gt;, our output is looking much smaller! This purging will only happen when you’re running a production build, so that your computer isn’t working overtime to purge assets each time you hit save during development. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FTkeHiWMH8W5muAE_FutR96t_wNjdCUfOmYEVaZ3hcQGSrTRIzUD7TcaJMhByAreZPzgKyymkfkAF0KmlYtQg81qPPEz0KQ-wz6Zjy456oK6hu_O4GDImpiTINXqoVjn6O8uIImla" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FTkeHiWMH8W5muAE_FutR96t_wNjdCUfOmYEVaZ3hcQGSrTRIzUD7TcaJMhByAreZPzgKyymkfkAF0KmlYtQg81qPPEz0KQ-wz6Zjy456oK6hu_O4GDImpiTINXqoVjn6O8uIImla"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Notes
&lt;/h2&gt;

&lt;p&gt;Congrats, you’ve now got a working, performance optimized WordPress Theme running TailwindCSS! Please get in touch if you’ve got any notes or suggestions to make this process easier, or if you want to share your sites that you’ve built with Tailwind and WordPress.&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>wordpress</category>
      <category>design</category>
      <category>webpack</category>
    </item>
    <item>
      <title>How to Automate SEO Checks Using Python &amp; Bash – The Beginner’s Guide (Part 1)</title>
      <dc:creator>Ciaran</dc:creator>
      <pubDate>Tue, 04 Aug 2020 18:51:51 +0000</pubDate>
      <link>https://dev.to/slemonade/how-to-automate-seo-checks-using-python-bash-the-beginner-s-guide-part-1-2mo6</link>
      <guid>https://dev.to/slemonade/how-to-automate-seo-checks-using-python-bash-the-beginner-s-guide-part-1-2mo6</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/knightspore/missing-link"&gt;MissingLink&lt;/a&gt; is a script I created to monitor a network of sites for missing links (internal or external), scripts, and images. I found it hard to monitor for broken links multiple sites centered around long-form content. One morning, I looked into automating the process with Python and discovered it would be a lot easier than I had expected.&lt;/p&gt;

&lt;p&gt;It’s also just plain old fun to be able to automate these checks using open source tools like &lt;a href="https://github.com/bartdag/pylinkvalidator"&gt;PyLinkValidator&lt;/a&gt;. For me, creating MissingLink was a great way to get a little deeper into using Shell Scripts, Python Packages, and my web server, so I decided to write a little breakdown of how it works, and how you can use it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Finding Broken Links with MissingLink
&lt;/h2&gt;

&lt;p&gt;Before following any of my instructions, you’re going to want to make sure you have Python and Pip installed. In addition, if you’re on Windows you’ll want to use a terminal application like &lt;a href="https://www.atlassian.com/git/tutorials/git-bash"&gt;Git Bash&lt;/a&gt; so you can easily use the command line to interact with the script.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installation and Target Domains
&lt;/h3&gt;

&lt;p&gt;When you’re all set up and ready to go, you can begin by installing &lt;a href="https://github.com/bartdag/"&gt;bartdag’s&lt;/a&gt; PyLinkValidator package for Python.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pip install pylinkvalidator&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Once you have installed PyLinkValidator, clone the MissingLink GitHub repo.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git clone https://github.com/knightspore/missing-link.git&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;When the download finishes, take a look at the files and folders – purely for your own interest. You’ll want to start with an edit of the cfg/domains.txt file. Nano is a simple command-line text editor – I’ve provided alternatives below so that you can use your preferred editor to open the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Edit in Terminal
nano cfg/domains.txt

# Edit with Visual Studio Code
code cfg/domains.txt

# Edit with Sublime Text
subl cfg/domains.txt

# Edit with Atom
atom cfg/domains.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Domains.txt is the file which stores the list of domains you want to crawl with MissingLink. Simply add the target domains in the format “website.com” as pictured below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ciaran.co.za
parabyl.co.za

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s also important to remember that you need to leave one blank line at the end of the file for it to work correctly – so after you’ve entered your last target domain, make sure to hit return (enter) before you save your changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check your Domains for Broken Links
&lt;/h2&gt;

&lt;p&gt;Now that you’re all set, execute run.sh in the main directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bash run.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give the crawl a little while to finish (it takes longer on larger sites, naturally) and you’ll find two new folders in your directory: crawl and report.&lt;/p&gt;

&lt;p&gt;If you don’t see these folders, or if the report is blank, there’s a chance that you’ve avoided having any broken links on your site! While this is a good thing, it does make for a particularly unspectacular demonstration of MissingLink.&lt;/p&gt;

&lt;p&gt;Go ahead and add a link to one of your pages which leads to a 404, just so you can see some results. I usually like to use radicalturnip.com.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note:&lt;/em&gt; if you’re crawling many domains and the computer you’re using isn’t very powerful, this might take a while. I like to use &lt;a href="https://www.vultr.com/?ref=8650167"&gt;one of my Vultr servers&lt;/a&gt; to run these checks. I can spin up a new server in minutes, SSH in, and start working from there to avoid putting a strain on my mid-range laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  Timeout: Why SEO Health Checks are Important
&lt;/h2&gt;

&lt;p&gt;SEO health checks should be part of any maintenance routine – and broken links aren’t the best thing for Googlebot to stumble across while crawling a page. While there are plenty of plugins that can notify you when a link breaks, many of us want to keep our sites running with as few plugins as possible to save on performance.&lt;/p&gt;

&lt;p&gt;Learning to do these checks manually is important – even if, in this case, that means browsing to a page and clicking on each link to see what’s broken (and why).&lt;/p&gt;

&lt;p&gt;Understanding how to find the errors that you’re looking for will help you better use third-party tools like MissingLink for SEO checks. You can get a better understanding of the kind of errors you’re looking for, and where to refine the parameters of your tools so you don’t end up with massive reports and crawl logs to sift through each week.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Your Crawl Report
&lt;/h2&gt;

&lt;p&gt;By now your crawl should have finished. As I mentioned before, your report-ready list of broken links will be available in the /report folder – as well as a full crawl log available in /crawl. You will probably only deal with the former, but take a look at your full crawl logs if you want a better idea of what’s happening behind the scenes.&lt;/p&gt;

&lt;p&gt;Luckily I only had one broken link on &lt;a href="https://parabyl.co.za/"&gt;parabyl.co.za&lt;/a&gt; – it’s a link to the Instagram account of a 3D artist friend of mine, who did cover art for my last album.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broken Links for parabyl | 2020-08-04

  not found (404): https://www.instagram.com/scumboy.pdf/?hl=en
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I can simply go and replace that link so that &lt;a href="https://www.instagram.com/scumboy.69/"&gt;Scumboy&lt;/a&gt; can be correctly credited (and to make sure search engines don’t knock me down in the ranks for having broken links). But the question is, where does this broken link exist?&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Fix Broken Links (404) on Your Website
&lt;/h3&gt;

&lt;p&gt;This is where the crawl logs come in handy. If I navigate to crawl/parabyl/parabyl-links.txt I can see a neat breakdown of all the pages where this broken link was found.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  not found (404): https://www.instagram.com/scumboy.pdf/?hl=en
    from https://parabyl.co.za
    from https://parabyl.co.za/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, I’m ready to fix the link!&lt;/p&gt;

&lt;p&gt;Out of interest – the reason my domain appears to be “listed twice” here is that the URL I entered had no trailing slash – and as such was redirected to one with a trailing slash. While trailing slashes themselves are not recommended for SEO purposes, the fact that it resolves to one specific option is a good thing – and an important feature you can implement using &lt;a href="https://yoast.com/wordpress/plugins/seo/"&gt;Yoast on WordPress&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We’ve reached the end of part one of this tutorial – in part two, we’ll look at bash scripting in more detail in order to understand how I set limits and instructions that can be reused to ‘standardize’ a crawl with PyLinkValidator.&lt;/p&gt;

&lt;p&gt;This will cover some great basic terminal commands which can help you become a little faster with the command line, which in turn can help you become a bit more productive in your everyday work.&lt;/p&gt;

&lt;p&gt;If I’ve piqued your interest, go ahead and check out &lt;a href="https://ciaran.co.za/development-design-projects/"&gt;some of my other projects&lt;/a&gt; – you might be able to learn something new, or even help me out with something I’m struggling with.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>python</category>
      <category>automation</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
