<?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: Abi Raja</title>
    <description>The latest articles on DEV Community by Abi Raja (@abi).</description>
    <link>https://dev.to/abi</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%2F792576%2F9e166d16-8c5d-4321-8f10-2b0f2a7d6a31.png</url>
      <title>DEV Community: Abi Raja</title>
      <link>https://dev.to/abi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/abi"/>
    <language>en</language>
    <item>
      <title>Inside the head of an HTML document</title>
      <dc:creator>Abi Raja</dc:creator>
      <pubDate>Tue, 03 May 2022 01:13:06 +0000</pubDate>
      <link>https://dev.to/abi/inside-the-head-of-an-html-document-53e8</link>
      <guid>https://dev.to/abi/inside-the-head-of-an-html-document-53e8</guid>
      <description>&lt;p&gt;In a HTML document, the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; is the place where you put everything that's not content. This is where you tell the browser how to render your page and what other files like CSS or JS or fonts to download. It's also where you tell a search bot or a social media website like Facebook or Twitter about your website.&lt;/p&gt;

&lt;p&gt;Let's walk through one by one all the things you should include in your &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Browser Directives
&lt;/h2&gt;

&lt;p&gt;First up is &lt;code&gt;&amp;lt;meta charset="utf-8" /&amp;gt;&lt;/code&gt; . It directs the browser to treat all your HTML content as UTF-8 and not ASCII or some character encoding such as &lt;a href="https://en.wikipedia.org/wiki/ISO/IEC_8859-1"&gt;ISO-8859-1&lt;/a&gt;. I don't think this is strictly necessary if you already have &lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt; at the top of the file specifying that this document is an HTML5 document. HTML5 only supports UTF-8. And even if you remove the doctype and include &lt;code&gt;&amp;lt;meta charset="ISO-8859-1" /&amp;gt;&lt;/code&gt; , Chrome still treats it as UTF-8 but other browsers might not leading to potentially unpredictable behavior. So, the consensus is that you should always include this tag.&lt;/p&gt;

&lt;p&gt;A mobile-optimized website should include:&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;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without this tag, the mobile browser might render the page at desktop width say 1200px and then, scale the page down to fit the actual width of the device likely something much smaller like 390px. It will end up looking super zoomed out. With this tag however, things work as expected. The media query breakpoints you've set for lower widths will return true and the page will render as you intend it to on a smaller device.&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO
&lt;/h2&gt;

&lt;p&gt;Then, we have &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; which controls the text in the tab bar of the browser. It's also very important for SEO. It ends up being the Google search result's title. For SEO reasons, it is recommended that it's as close to 60 characters as possible. It also ends up being the default name under which the bookmark gets saved as in a user's browser.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;meta name="description" content="..."&amp;gt;&lt;/code&gt; is important for SEO reasons as well. Recommend length is 155-160 characters.&lt;/p&gt;

&lt;p&gt;I like to include &lt;code&gt;&amp;lt;meta name="robots" content="follow, index" /&amp;gt;&lt;/code&gt; although the default behavior of most search engine bots is to follow links and index all pages so technically, it's optional but doesn't hurt to be explicit.&lt;/p&gt;

&lt;p&gt;The canonical URL is really important for SEO reasons:&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://yourwebsite.com/article-title"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It lets the search engine know that canonical URL for the content on this page is the value specified using this tag. That way, I can syndicate this blogpost on dev.to and Medium but still have Google direct people to this page when my content ranks highly for a search keyword. So your actual website ends up getting the traffic rather than dev.to or Medium. Another reason this matters is that &lt;a href="https://moz.com/learn/seo/canonicalization"&gt;large-scale duplication can lower your search ranking&lt;/a&gt;. With canonical URLs, you are telling Google when something is a duplicate vs. not. Make sure you have consistent canonical URLs across your website: trailing slashes or not? www subdomain or not? HTTPS or not? (pick HTTPS).&lt;/p&gt;

&lt;p&gt;What about the keywords tag, &lt;code&gt;&amp;lt;meta name="keywords" content="seo, search engine optimization"/&amp;gt;&lt;/code&gt; ? I've seen a lot of websites use them but the &lt;a href="https://ahrefs.com/blog/meta-keywords/"&gt;consensus in the SEO community&lt;/a&gt; is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For 99.9% of people, the meta keywords tag is useless, and filling it out is a waste of time. You should only use it if you have a particular reason to do so, like using it for an internal keyword tagging system or an internal site search.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most search engines including the biggest one of them all, Google, disregard the tag.&lt;/p&gt;

&lt;p&gt;For more SEO tweaks, I generate a &lt;a href="https://www.seobility.net/en/seocheck/"&gt;free report here&lt;/a&gt;. It'll check many of the things described above. The Google Search Console is also very helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Social Media
&lt;/h2&gt;

&lt;p&gt;When a link gets shared on Twitter, this is how it looks:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a6JxFr5a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fnlklust66rgc2pn25t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a6JxFr5a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6fnlklust66rgc2pn25t.png" alt="Twitter social media preview" width="816" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Open Graph meta tags are what the website uses to render this tile.&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;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:title"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Loops"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:site_name"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Loops"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:url"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"https://loops.quest"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt;
  &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:description"&lt;/span&gt;
  &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Analyze Solana transactions. Trace how NFTs and tokens move across multiple accounts."&lt;/span&gt;
&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:type"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"website"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;property=&lt;/span&gt;&lt;span class="s"&gt;"og:image"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"%PUBLIC_URL%/og-image.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Title, site_name, URL and description pretty much just correspond to &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, website domain or name, canonical URL, and &lt;code&gt;&amp;lt;meta name="description"&amp;gt;&lt;/code&gt;, respectively.&lt;/p&gt;

&lt;p&gt;The type can be a few different types but typically it's either &lt;code&gt;article&lt;/code&gt; for a blogpost or &lt;code&gt;website&lt;/code&gt; for an app or an e-commerce website.&lt;/p&gt;

&lt;p&gt;For the image, &lt;a href="https://developers.facebook.com/docs/sharing/webmasters/images"&gt;Facebook recommends&lt;/a&gt;: "1200x630 or larger is preferred (up to 5MB). Stay close to a 1.91:1 aspect ratio to avoid cropping.". But I've found that following the image guidelines is no substitute for actually testing the previews.&lt;/p&gt;

&lt;p&gt;To test, I use ngrok to tunnel my local website to the public internet, and copy the URL into &lt;a href="https://www.opengraph.xyz/"&gt;this tool to look at the previews across platforms&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Open Graph tags are used by most social platforms, including Twitter. However, for Twitter, you are able to specify Twitter-specific tags as well. Twitter will use &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt; &lt;a href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started#opengraph"&gt;from the Open Graph tags&lt;/a&gt; so I don't bother re-specifying them. But there are some Twitter-specific tags worth including:&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;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:card"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"summary_large_image"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"twitter:site"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"@_abi_"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Summary card with large image is likely what you want for articles and websites but if you have a video instead, you can specify &lt;code&gt;player&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/summary-card-with-large-image"&gt;Twitter's image recommendation for the summary card with large image&lt;/a&gt; is slightly different from Facebook: "Images for this Card support an aspect ratio of 2:1 with minimum dimensions of 300x157 or maximum of 4096x4096 pixels. Images must be less than 5MB in size. JPG, PNG, WEBP and GIF formats are supported. Only the first frame of an animated GIF will be used. SVG is not supported."&lt;/p&gt;

&lt;p&gt;However, since the aspect ratio is only slightly from Facebook, you can probably skip using a different image.&lt;/p&gt;

&lt;p&gt;Besides the testing tool linked earlier, Facebook and Twitter offer their own tools as well: &lt;a href="https://developers.facebook.com/tools/debug/"&gt;Facebook&lt;/a&gt;&lt;br&gt;
and &lt;a href="https://cards-dev.twitter.com/validator"&gt;Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Others
&lt;/h2&gt;

&lt;p&gt;The only remaining thing we must include is a bevy of favicons. Here's &lt;a href="https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs"&gt;a great article by the author of PostCSS&lt;/a&gt; on what we need and why.&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;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/favicon.ico"&lt;/span&gt; &lt;span class="na"&gt;sizes=&lt;/span&gt;&lt;span class="s"&gt;"any"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- 32×32 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/icon.svg"&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"image/svg+xml"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"apple-touch-icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/apple-touch-icon.png"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!-- 180×180 --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"manifest"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/manifest.webmanifest"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then in the &lt;code&gt;manifest.webmanifest&lt;/code&gt; file,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"icons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/icon-192.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sizes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"192x192"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/icon-512.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"image/png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"sizes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"512x512"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your app is a progressive web app i.e. a website that can be installed to the home screen without using an App Store, you should fill out the &lt;a href="https://web.dev/add-manifest/"&gt;manifest file&lt;/a&gt; with more detail.&lt;/p&gt;

</description>
      <category>html</category>
      <category>seo</category>
      <category>webdev</category>
    </item>
    <item>
      <title>What is Tailwind? And how to set it up properly.</title>
      <dc:creator>Abi Raja</dc:creator>
      <pubDate>Wed, 02 Mar 2022 22:37:32 +0000</pubDate>
      <link>https://dev.to/abi/what-is-tailwind-and-how-to-set-it-up-properly-3n45</link>
      <guid>https://dev.to/abi/what-is-tailwind-and-how-to-set-it-up-properly-3n45</guid>
      <description>&lt;p&gt;I've been using Tailwind for CSS in my projects lately. At first glance, Tailwind looks pretty ugly and hard to decipher. Just look at this.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9ym9jwrzfsuq4izjfg1.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9ym9jwrzfsuq4izjfg1.png" alt="Tailwind is not pretty"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;It sure is ugly-looking but it works well! Drawing inspiration from &lt;a href="https://acss.io/" rel="noopener noreferrer"&gt;Atomic CSS&lt;/a&gt; and utility classes (1 class = 1 style), Tailwind makes a few strong design decisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Markup and style should live next to each other (bye, bye stylesheets): This makes it easier to write and update components since you don't have to change two different files. Global CSS is also hard to maintain over time since a change in the global namespace could affect any number of things on your website.&lt;/li&gt;
&lt;li&gt;Coming up with class names is a waste of time.&lt;/li&gt;
&lt;li&gt;CSS is an expressive style language that maps directly to browser rendering models and so, there's no need to learn a new mental model for styling (which some other CSS frameworks force you to).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You might note that all of this is true for inline CSS as well! Why not just use regular CSS and just avoid using stylesheets?&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="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&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;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;True. You do get these benefits with inline CSS. But Tailwind does better in a couple of ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;With inline CSS, you can't have media queries or hover states. In Tailwind, you can do this via modifiers which you can add to any utility class: &lt;code&gt;bg-sky-600 hover:bg-sky-700&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Tailwind comes with a design system (colors, fonts, spacing, etc.). You can write stuff like &lt;code&gt;m-2&lt;/code&gt; (margin of 2 units) rather than specify exact pixels. As a result, across your website, spacing will be uniform, colors will come up from your theme and so on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's the essence of Tailwind. It's a very low-level CSS framework composed of a bunch of utility classes and a customizable design system.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Tailwind work?
&lt;/h2&gt;

&lt;p&gt;Tailwind processes all of your code, looking at &lt;code&gt;className&lt;/code&gt; properties in React components but not just that. In case you have some dynamically generated classes (&lt;code&gt;const classes = disabled ? "color-gray-100" : "color-indigo-100"&lt;/code&gt; ), Tailwind will also look for utility classes in your JS. Once it parses all utility classes in the code, it generates the corresponding CSS and writes them to a file. I use it with React and it's supported with Create React App v5 and above.&lt;/p&gt;

&lt;p&gt;If your framework doesn't support it (I had a hard time getting it working in CRA v4), you can always use the CLI to watch and generate the CSS file. You'll specify the directory to be watched. And you'll have to load the output CSS file in your HTML. &lt;a href="https://tailwindcss.com/docs/content-configuration#it-just-isn-t-working-properly" rel="noopener noreferrer"&gt;Good setup and troubleshooting tips here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editor Setup
&lt;/h2&gt;

&lt;p&gt;VS code support via the official Tailwind plugin makes Tailwind very pleasant to write and less ugly to read. The plugin offers autocomplete so you don't need to remember every utility class. It also lets you hover over utility classes to see the CSS they will generate.&lt;/p&gt;

&lt;p&gt;You should definitely add the following to your VS Code settings for your Tailwind project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"css.validate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"editor.quickSuggestions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"strings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second setting tells VS Code to autocomplete not just at the start of a string but also in the middle. Without this, you'll only get autocomplete for utility classes when your cursor is at the end of &lt;code&gt;className="&lt;/code&gt; but not when it's at the end of &lt;code&gt;className="mx-4&lt;/code&gt;. That is, without this setting, you only get autocomplete for the first class in a list.&lt;/p&gt;

&lt;p&gt;Now that we finally don't have to worry about naming classes, what else can we bike shed about? Well, the order of utility classes, of course. Fret not. The Tailwind just released a &lt;a href="https://tailwindcss.com/blog/automatic-class-sorting-with-prettier" rel="noopener noreferrer"&gt;Prettier plugin&lt;/a&gt; last month to end these pointless debates. The Prettier plugin automatically sorts classes. And it's not configurable.&lt;/p&gt;

&lt;p&gt;One annoyance with the plugin is that the features only work for values of &lt;code&gt;className&lt;/code&gt; attributes.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yp6gccfhvzrqdvb1yqd.png" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9yp6gccfhvzrqdvb1yqd.png" alt="No plugin support for arbitrary strings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My only other gripe is that the linting seems finicky.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;From the docs, "the most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files." If you have code like &lt;code&gt;error ? 'text-red-600' : 'text-green-600'&lt;/code&gt;, CSS will be generated for &lt;code&gt;text-red-600&lt;/code&gt; and &lt;code&gt;text-green-600&lt;/code&gt;. But if you have &lt;code&gt;text-{{ error ? 'red' : 'green' }}-600&lt;/code&gt;", your Tailwind-generated CSS file will in fact not contain any classes &lt;code&gt;text-red-600&lt;/code&gt; and &lt;code&gt;text-green-600&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This stumped me for a bit. I didn't know this and I went about creating an invisible &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; that had all the classes that were being used with conditional logic. But if you use unbroken strings for all class names, that solves it.&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>css</category>
      <category>webdev</category>
      <category>react</category>
    </item>
  </channel>
</rss>
