{
    "componentChunkName": "component---src-templates-post-js",
    "path": "/blog/rebuilding-my-portfolio-site-with-tailwind-css/",
    "result": {"data":{"site":{"siteMetadata":{"title":"Danniel Hansel"}},"mdx":{"id":"6716a85b-6801-525e-b2ea-5448c01bf60d","excerpt":"In this post, we’ll talk about how switching to utility-first CSS framework like Tailwind CSS might work for you. Also, we’ll explore Tailwind CSS on a broad…","body":"const _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nconst _frontmatter = {\n  \"slug\": \"rebuilding-my-portfolio-site-with-tailwind-css\",\n  \"title\": \"Rebuilding my portfolio site with Tailwind CSS\",\n  \"date\": \"2021-05-13\",\n  \"author\": \"Danniel Hansel\",\n  \"description\": \"My experience with Tailwind CSS.\",\n  \"published\": true,\n  \"featured\": true,\n  \"categories\": [\"react\"],\n  \"tags\": [\"javascript\", \"react\", \"gatsby\", \"tailwind-css\", \"bootstrap\"],\n  \"bannerUrl\": \"https://res.cloudinary.com/dehanz-dev/image/upload/v1640453752/dannielhansel.com/content/blog/rebuild-portfolio_s7cuq0.webp\",\n  \"bannerCredit\": \"Photo by [Aziz Acharki](https://unsplash.com/photos/6YpwRf0iUa4) on [Unsplash](https://unsplash.com)\"\n};\nconst layoutProps = {\n  _frontmatter\n};\nconst MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  let {\n    components\n  } = _ref,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, `In this post, we’ll talk about how switching to utility-first CSS framework like Tailwind CSS might work for you.`), mdx(\"p\", null, `Also, we’ll explore Tailwind CSS on a broad level.`), mdx(\"p\", null, `On top of that, we’ll also be building a simple GatsbyJs App from scratch using Tailwind CSS including Tailwind CSS installation, configuration, and designing options.`), mdx(\"h1\", null, `What was I using before?`), mdx(\"p\", null, `Previously, I decided to build my own portfolio site with GatsbyJs and Bootstrap as the CSS framework. The reason why I chose to go with this tech stack is because I have been building several React/GatsbyJs websites in the past and I am also quite familiar with utilizing the Bootstrap framework. Although I was able to get it up and running fairly quickly, there was still something that I wasn’t quite happy about the user interface. Until I discovered Tailwind CSS and what it can do to improve my site and essentially meet my satisfaction.`), mdx(\"h1\", null, `Why did I make the switch?`), mdx(\"p\", null, `My goal after discovering Tailwind CSS was to simply rebuild any complex user interfaces without having my site to look alike any other sites out there. `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `This is the `, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `difference`), ` between Bootstrap and Tailwind CSS.`), ` If you have never used and worked with Bootstrap before, you can tell right off the bat when a site is using Bootstrap framework.`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `(hint: just simply look at the Bootstrap buttons and compare them to Tailwind CSS buttons!)`)), mdx(\"p\", null, `However, don’t get me wrong here, Bootstrap is still great and does the job for certain project needs and requirements. In fact, I do still use Bootstrap for my other sites because it comes with a lot of pre-styled components out of the box that are ready to use and look good. `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `If you are just wanting to whip up an absolutely basic interface for a quick PoC (proof of concept), then Bootstrap is your go-to`), `.`), mdx(\"p\", null, `Having that in mind, `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `firstly`), ` I want my new portfolio site to be able to easily handle `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `consistency`)), ` in terms of padding, margins, colors, and sizes. With Tailwind CSS, I could just write utility class and then repeatedly use them in my codebase.`), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `Secondly`), `, I want something that can speed up the process of handling `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `responsiveness`)), ` of the site from small screens to bigger screens. Tailwind provides five `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `breakpoints`), ` by default to serve different common device resolutions. This makes it a piece of cake to build complex responsive interfaces without ever leaving your HTML.`), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `Thirdly`), `, I want something that doesn’t make it harder on me as the developer to support `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `dark mode.`)), ` Dark mode has become the first-class feature of many operating systems. To make this as easy as possible, Tailwind comes with a `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `‘dark’`), ` variant that lets you style your site however you want when dark mode is enabled.`), mdx(\"p\", null, `And `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `lastly`), `, I want to finish this project feeling more `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `productive`)), ` than ever when it comes to developing the user interfaces. Since Tailwind comes with a set of utility classes, once you get used to the custom terms and vocabulary, you will feel like you are flying! All in all, Tailwind’s system is a masterpiece of design which I as a developer love it and feel empowered by it.`), mdx(\"h1\", null, `What is Tailwind CSS?`), mdx(\"p\", null, `Okay, then let’s talk about `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, mdx(\"em\", {\n    parentName: \"strong\"\n  }, `“what”`), ` is Tailwind CSS?`), ` Tailwind CSS is a utility-first CSS framework that provides you with a set of low-level utility classes. This framework uses `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `atomic CSS`), ` (or functional CSS) which is essentially a delivery mechanism that allows you and I, as developers, to apply the system to the UI. On top of that, it uses PostCSS to process the final output and it comes with PurgeCSS which removes unused CSS from your project file.`), mdx(\"p\", null, `In this post, we’ll be using the Gatsby Default Starter. If you’ve never used Gatsby before, I have included a quick tutorial on how to create a new Gatsby project, but you can read more about it `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.digitalocean.com/community/tutorials/gatsbyjs-gatsby-first-steps\"\n  }, `here`), ` from the docs. But the idea here is simple, you can use any of your favorite framework or library and install Tailwind CSS to handle the styling for you!`), mdx(\"h1\", null, `Part 1: Gatsby Quick Installation Guide`), mdx(\"h2\", null, `Step 1: System requirements`), mdx(\"p\", null, `Make sure you have Node.js, Git, and other tools required to get started with your first Gatsby project. To learn more about it, check out the `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.gatsbyjs.com/docs/tutorial/part-zero/\"\n  }, `Gatsby docs`), `.`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://git-scm.com/\"\n  }, `Git`), ` (v2.13 or greater)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://nodejs.org/en/\"\n  }, `NodeJS`), ` (v8.2.0 0r higher)`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://www.npmjs.com/\"\n  }, `NPM`), ` (v6 or greater) or `, mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https://yarnpkg.com/\"\n  }, `Yarn`))), mdx(\"p\", null, `All of these must be available in your `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `PATH`), `. To verify things are set up properly, you can run this:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `git --version\nnode --version\nnpm --version # or yarn --version\n`)), mdx(\"p\", null, `If you have trouble with any of these, learn more about the PATH environment\nvariable and how to fix it here for `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/\"\n  }, `windows`), ` or\n`, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://stackoverflow.com/questions/24306398/how-to-add-mongo-commands-to-path-on-mac-osx/24322978#24322978\"\n  }, `mac/linux`), `.`), mdx(\"h2\", null, `Step 2: Download/Install the Gatsby CLI package:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `npm install -g gatsby-cli\n`)), mdx(\"p\", null, `Check out all the available commands:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `gatsby --help\n`)), mdx(\"h2\", null, `Step 3: Create a Gatsby site using the default starter template`), mdx(\"p\", null, `Stick this in your terminal and hit enter`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `gatsby new my-first-gatsby-project https://github.com/gatsbyjs/gatsby-starter-default\n`)), mdx(\"p\", null, `Change into the directory:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `cd my-first-gatsby-project\n`)), mdx(\"p\", null, `Start the development server:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `gatsby develop\n`)), mdx(\"p\", null, `View your site locally. Open up a new tab in your browser and navigate to: `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"http://localhost:8000/\"\n  }, `http://localhost:8000/`)), mdx(\"h1\", null, `Part 2: Setting up Tailwind CSS`), mdx(\"h2\", null, `Step 1: Create two configs for Tailwind CSS and PostCSS:`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `Note: You might not have do this, so check if they're preinstalled in your root directory.`)), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `touch tailwind.config.js\n`)), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `touch postcss.config.js\n`)), mdx(\"p\", null, `Add this default configuration inside tailwind.config.js:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `// inside tailwind.config.js\nconst defaultTheme = require(\"tailwindcss/defaultTheme\")\nconst plugin = require(\"tailwindcss/plugin\")\nconst colors = require(\"tailwindcss/colors\")\n\nmodule.exports = {\n  mode: \"jit\",\n  // purge: {              // this is not needed for tailwind 3.0\n  //   content: [\"./src/**/*.js\"],\n  // },\n  content: [\"./src/**/*.js\"],\n  darkMode: \"class\", // or 'media' or 'class'\n  theme: {\n    screens: {\n      ...defaultTheme.screens,\n      xs: \"475px\",\n    },\n    textColor: theme => ({\n      ...theme(\"colors\"),\n      primary: \"#397E89\",\n      secondary: \"#883377\",\n    }),\n    extend: {\n      fontFamily: {},\n    },\n  },\n  variants: {\n    extend: {},\n  },\n  plugins: [],\n}\n`)), mdx(\"h2\", null, `Step 2: Install Tailwind CSS and add NPM dependencies:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `npm install --save gatsby-plugin-postcss tailwindcss\n`)), mdx(\"p\", null, `Stick this plugin in:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `// inside gatsby-config.js\nmodule.exports = {\n  // ...rest\n  plugins: [\n    {\n      resolve: \\`gatsby-plugin-postcss\\`,\n      options: {\n        postCssPlugins: [require(\"tailwindcss\")],\n      },\n    },\n  ],\n}\n`)), mdx(\"h2\", null, `Step 3: Import Tailwind CSS in the src/components/layout.css `, mdx(\"em\", {\n    parentName: \"h2\"\n  }, `(at the very top)`), `:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `// inside layout.css\n@tailwind base;\n@tailwind components;\n@tailwind utilities;\n`)), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `Congrats! You have now successfully added TailwindCSS to your Gatsby project!`)), mdx(\"p\", null, `Next, it’s time to add Tailwind classes to your HTML. `, mdx(\"em\", {\n    parentName: \"p\"\n  }, `In this post, we are only going to create a basic Hero component on landing page and play around with the styling options.`)), mdx(\"h1\", null, `Part 3: Creating a basic Landing page`), mdx(\"p\", null, `Before we start, `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `let's first kill the dev server`), `. Navigate to your terminal and ctrl + C.`), mdx(\"h2\", null, `Navigate to index.js file and replace the IndexPage component with this:`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `const IndexPage = () => (\n  <Layout>\n    <Seo title=\"Home\" />\n    <div\n      className=\"flex items-center bg-gradient-to-br from-green-400 via-blue-500 to-purple-500\n      shadow-inner min-h-screen\"\n    >\n      <div className=\"bg-white w-full py-6 shadow-2xl\">\n        <div className=\"mx-auto container w-4/5 sm:w-3/5\">\n          <div className=\"self-center items-center mb-4\">\n            <h1 className=\"capitalize font-bold text-xl text-center text-secondary\">\n              Your Name\n            </h1>\n            <h3 className=\"uppercase font-semibold text-primary text-center\">\n              Full Stack Developer\n            </h3>\n            <div className=\"grid justify-items-center\">\n              <button\n                className=\"transition duration-500 ease-in-out transform hover:-translate-y-1\n              hover:scale-110 bg-gradient-to-r from-green-400 to-blue-500 hover:from-blue-500\n              hover:to-purple-500 text-white font-bold py-2 px-4 border-b-4 border-blue-700\n              hover:border-purple-500 rounded mt-6\"\n              >\n                Contact Me!\n              </button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </Layout>\n)\n`)), mdx(\"h3\", null, `Run the development server to rebuild the project.`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-shell\"\n  }, `gatsby develop\n`)), mdx(\"p\", null, `Navigate to your `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"http://localhost:8000/\"\n  }, `localhost server`), ` to see the result! 🙌`), mdx(\"h1\", null, `Styling in Tailwind CSS`), mdx(\"h2\", null, `Colors in Tailwind CSS`), mdx(\"p\", null, `Inside `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `tailwind.config.js`), ` file, we can override Tailwind’s default `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tailwindcss.com/docs/customizing-colors\"\n  }, `color palette`), `, extend it or even disable it.`), mdx(\"p\", null, `In our example, we have added two colors as `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `‘primary’`), ` and `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `‘secondary’`), `.`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `// inside tailwind.config.js\ntheme: {\n    textColor: theme => ({\n      ...theme(\"colors\"),\n      primary: \"#397E89\",\n      secondary: \"#883377\",\n    }),\n        ...\n  },\n`)), mdx(\"p\", null, `To apply it to your HTML, you can simply just add it using inline style as `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `‘text-primary’`), ` or `, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `‘text-secondary’`), `.`), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\"\n  }, `<h1 className=\"capitalize font-bold text-xl text-center text-secondary\">\n    Your Name\n</h1>\n\n<h3 className=\"uppercase font-semibold text-primary text-center\">\n    Full Stack Developer\n</h3>\n\n`)), mdx(\"h2\", null, `Styling a Button`), mdx(\"p\", null, `Tailwind comes with a palette of colors that you can choose from. I'd recommend you to check out all the colors they have and play around with it. In our example, we are using a `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `gradient of colors`), `.`), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `bg-gradient-to-r from-green-400 to-blue-500`)), mdx(\"h2\", null, `Hovering a component (Pseudo classes with inline styling)`), mdx(\"p\", null, `In our example, we simply use a gradient of colors when a button is being hovered.`), mdx(\"p\", null, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, `hover:from-blue-500 hover:to-purple-500`)), mdx(\"h2\", null, `Other low-level utility classes that we’ve used in our example:`), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `font-bold`), `: add bold font;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `flex`), `: display: flex;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `items-center`), `: align-items: center;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `shadow-inner`), `: box shadow`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `min-h-screen`), `: setting minimum height of an element;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `w-full`), `: width: 100%;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `w-4/5`), `: width: 80%;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `self-center`), `: align-self: center;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `py-6`), `: padding-top: 1.5rem; padding-bottom: 1.5rem;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `mb-4`), `: margin-bottom: 1rem;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `capitalize`), `: text-transform: capitalize;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `uppercase`), `: text-transform: uppercase;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `text-xl`), `: font-size: 1.25rem; line-height: 1.75rem;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `text-center`), `: text-align: center;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `justify-items-center`), `: justify-items: center;`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `transition`), `: transition property`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `bg-green-400`), `: to use green as the button’s background color`), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, `hover:bg-blue-700`), `: to change the blue color when hovering over the button`)), mdx(\"h1\", null, `The Downsides of Tailwind CSS 📉`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, `As Tailwind CSS becomes more revolutionized, there are definitely some challenges. However, I am going to talk about the challenges I faced on the underlying concept of utility-first framework.`)), mdx(\"h2\", null, `Repeatable CSS`), mdx(\"p\", null, `With utility-first, you are going to have repeated classes. This could get annoying as your project eventually grows larger. Compare to regular CSS, you could just create a class that does the same job and you can reuse that class in multiple components.`), mdx(\"p\", null, `Of course, you can find a way to not repeat the classes but that defeats the purpose of using a utility-first concept because the goal is to minimize the handling of CSS to your project.`), mdx(\"h2\", null, `Readability`), mdx(\"p\", null, `Take our button for example. If you were to have multiple buttons on your site, you would have a long list of classes for each button and as you can already guess, It will be hard to read. This could be the biggest downfall of utility-first concept. As your project grows, you are more than likely going add tons of CSS classes to your project.`), mdx(\"h2\", null, `Atomic CSS downsides`), mdx(\"p\", null, `Atomic CSS is not ideal for performance. You would have to ship more CSS to the browser than necessary because no tooling can extract the per-page critical CSS. As your utility-based CSS library grows, so does the amount of CSS you ship to your users, leaving you having to build more tools to remove styles that you were never going to use in the first place.`), mdx(\"h1\", null, `Conclusion`), mdx(\"h3\", null, `Was it worth switching to Tailwind CSS?`), mdx(\"p\", null, `Most definitely, Yes! ✅After successfully rebuilding my portfolio site using Tailwind, I am loving every piece of it. If you love a good design, you'd definitely love Tailwind, especially with just how it gives you the aesthetic and modern feel and look. `, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `Very important for building the `, mdx(\"a\", {\n    parentName: \"strong\",\n    \"href\": \"https://headlessui.dev/\"\n  }, `user interface`), ` to enhance user experience.`), ` 👀 They also have a great `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/tailwindlabs/tailwindcss/discussions\"\n  }, `community`), ` and a well detailed `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tailwindcss.com/docs/installation\"\n  }, `documentation`), `.`), mdx(\"blockquote\", null, mdx(\"p\", {\n    parentName: \"blockquote\"\n  }, mdx(\"strong\", {\n    parentName: \"p\"\n  }, `UPDATE`), `: They had just recently upgraded to `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tailwindcss.com/docs/upgrade-guide\"\n  }, `Tailwind 3.0`), `.`)), mdx(\"p\", null, `Always keep this in mind, every tool and technology out there has tradeoffs. So it's always good to `, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://play.tailwindcss.com/\"\n  }, `play around`), ` and test them. I hope that I’ve given you an overview of how Tailwind has helped me improve my project. 😇`));\n}\n;\nMDXContent.isMDXComponent = true;","timeToRead":6,"fields":{"slug":"/blog/rebuilding-my-portfolio-site-with-tailwind-css/"},"frontmatter":{"slug":"rebuilding-my-portfolio-site-with-tailwind-css","title":"Rebuilding my portfolio site with Tailwind CSS","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1640453752/dannielhansel.com/content/blog/rebuild-portfolio_s7cuq0.webp","bannerCredit":"Photo by [Aziz Acharki](https://unsplash.com/photos/6YpwRf0iUa4) on [Unsplash](https://unsplash.com)","tags":["javascript","react","gatsby","tailwind-css","bootstrap"],"description":"My experience with Tailwind CSS.","date":"May 13, 2021"}},"relatedMdxs":{"posts":[{"id":"1bd58e0e-11af-50e2-b16f-1284d82c7cea","timeToRead":7,"slug":"blog/7-basic-rules-for-self-improvement","frontmatter":{"title":"7 Basic Rules for Self Improvement","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1639602245/dannielhansel.com/content/blog/7-basic-rules-for-self-improvement_vhqngn.jpg","bannerCredit":"Photo by [Alif Ngoylung](https://unsplash.com/photos/-A_Sx8GrRWg) on [Unsplash](https://unsplash.com)","slug":"7-basic-rules-for-self-improvement","tags":["personal","productivity"],"description":"What I have learned from doing self-development work.","date":"November 27, 2020"}},{"id":"edc10d92-c4e5-58c7-a0ec-e0a4fb636181","timeToRead":5,"slug":"blog/powerful-morning-routines-that-will-change-your-life","frontmatter":{"title":"Powerful Morning Routines that Will Change Your Life","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1639601696/dannielhansel.com/content/blog/rebuilding-my-portfolio-site-with-tailwind-css_rqnsbb.jpg","bannerCredit":"Photo by [lucas Favre](https://unsplash.com/photos/JnoNcfFwrNA) on [Unsplash](https://unsplash.com)","slug":"powerful-morning-routines-that-will-change-your-life","tags":["personal","productivity"],"description":"Killer morning routines to better your life and reach your full potential.","date":"February 03, 2021"}},{"id":"f2db5aef-b482-532f-9a92-f93463cc0a26","timeToRead":2,"slug":"blog/the-debate-between-library-vs-package-vs-framework-vs-module","frontmatter":{"title":"The Debate between Module vs Package vs Library vs Framework","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1640453749/dannielhansel.com/content/blog/package-library_xqm8ix.webp","bannerCredit":"Photo by [Bench Accounting](https://unsplash.com/photos/MGaFENpDCsw) on [Unsplash](https://unsplash.com)","slug":"the-debate-between-library-vs-package-vs-framework-vs-module","tags":["software-engineering","tools"],"description":"One of the most frequent asked question in Software Engineering.","date":"January 10, 2021"}},{"id":"b15e2892-c0b8-5bbc-966d-3bfb10cac6c2","timeToRead":2,"slug":"blog/fetching-data-from-firestore","frontmatter":{"title":"Fetching data from Firestore","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1639602322/dannielhansel.com/content/blog/fetching-data-from-firestore_zalbof.jpg","bannerCredit":"Photo by [Tobias Fischer](https://unsplash.com/photos/PkbZahEG2Ng) on [Unsplash](https://unsplash.com)","slug":"fetching-data-from-firestore","tags":["react","ssr","database","nextjs","database"],"description":"This quick guide shows you how to create a React custom hook to fetch data from Cloud Firestore.","date":"November 08, 2021"}},{"id":"cf047db2-ca90-5b7d-85d4-62dd9bec16bd","timeToRead":2,"slug":"about/about-me","frontmatter":{"title":"About Danniel Hansel","author":"Danniel Hansel","bannerUrl":null,"bannerCredit":null,"slug":null,"tags":null,"description":"Learn about Danniel Hansel and how he got to where he is","date":null}},{"id":"607bdcda-0d6c-5f06-9a34-7c59aca6989d","timeToRead":1,"slug":"blog/initial-setup-for-cloud-firestore-database","frontmatter":{"title":"Initial setup for Cloud Firestore database","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1639602371/dannielhansel.com/content/blog/initial-setup-for-cloud-firestore-database_p8rflb.jpg","bannerCredit":"Photo by [Jan Antonin Kolar](https://unsplash.com/photos/lRoX0shwjUQ) on [Unsplash](https://unsplash.com)","slug":"initial-setup-for-cloud-firestore-database","tags":["react","ssr","backend","nextjs","database"],"description":"This quick guide shows you how to set up Cloud Firestore for your React application.","date":"November 01, 2021"}},{"id":"f5e43818-6b9e-539f-b958-b022a7c84719","timeToRead":2,"slug":"blog/image-types-vector-vs-pixel","frontmatter":{"title":"Image types: Vector vs. Pixel","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1644037300/dannielhansel.com/content/blog/pixal-vs-vector_dkaxg1.jpg","bannerCredit":"Photo by [Umberto](https://unsplash.com/photos/deb2EnbWPr8) on [Unsplash](https://unsplash.com)","slug":"image-types-vector-vs-pixel","tags":["performance"],"description":"Why you should go for Vector vs. Pixel.","date":"December 03, 2021"}},{"id":"b86814e4-5866-5e31-91ff-d0a8b9ea363b","timeToRead":1,"slug":"blog/handling-external-links-for-mdx-files-in-gatsby","frontmatter":{"title":"Handling External Links for MDX files in Gatsby","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1640453751/dannielhansel.com/content/blog/external-link_roctbf.webp","bannerCredit":"Photo by [Eric Mclean](https://unsplash.com/photos/sxiSod0tyYQ) on [Unsplash](https://unsplash.com)","slug":"handling-external-links-for-mdx-files-in-gatsby","tags":["ssg","react","gatsby"],"description":"The easiest way to open links in a new tab when using gatsby-plugin-mdx.","date":"December 10, 2021"}},{"id":"f3c648a6-01ba-585b-99f5-85cf76a54f73","timeToRead":1,"slug":"testimonial/testimonial","frontmatter":{"title":"Testimonial 1","author":"Maggie","bannerUrl":null,"bannerCredit":null,"slug":null,"tags":null,"description":null,"date":null}},{"id":"4e777b1c-f8d9-57f8-9799-cfd6f1af27a2","timeToRead":1,"slug":"about/about","frontmatter":{"title":"About Me","author":"Danniel Hansel","bannerUrl":null,"bannerCredit":null,"slug":null,"tags":null,"description":"Learn about Danniel Hansel and what he does","date":null}},{"id":"c63edb7e-453e-5bac-ab79-6514bfcc5983","timeToRead":1,"slug":"project/project10/project10","frontmatter":{"title":"Book List Tracker","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"23fb515e-31a0-5407-b16b-d9b688f2b5af","timeToRead":1,"slug":"blog/updating-data-from-firestore","frontmatter":{"title":"Updating data from Firestore","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1639602451/dannielhansel.com/content/blog/updating-data-from-firestore_zvsbav.jpg","bannerCredit":"Photo by [Piron Guillaume](https://unsplash.com/photos/U4FyCp3-KzY) on [Unsplash](https://unsplash.com)","slug":"updating-data-from-firestore","tags":["react","ssr","database","nextjs","backend"],"description":"This quick guide shows you how to handle CRUD operations from Firestore database.","date":"November 27, 2021"}},{"id":"6f5b7bcc-efa4-5084-8b34-cec1b0506f16","timeToRead":1,"slug":"blog/my-favorite-tech-podcasts","frontmatter":{"title":"My Favorite Tech Podcasts","author":"Danniel Hansel","bannerUrl":"https://res.cloudinary.com/dehanz-dev/image/upload/v1644037050/dannielhansel.com/content/blog/my-favorite-podcasts_ksnqce.jpg","bannerCredit":"Photo by [Mohammad Metri](https://unsplash.com/photos/1oKxSKSOowE) on [Unsplash](https://unsplash.com)","slug":"my-favorite-tech-podcasts","tags":["personal","productivity"],"description":"I've compiled a list of my favorite tech and non-tech podcasts.","date":"January 15, 2022"}},{"id":"6563d4b8-ff14-5280-8e20-7f7b930b8f73","timeToRead":1,"slug":"project/project1/project1","frontmatter":{"title":"The Crab Station & Oyster Bar","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["React","GatsbyJS","Bootstrap","Contentful","Netlify","AWS"],"description":null,"date":null}},{"id":"57c19c65-eeb5-5d52-ae1f-c83b4caef2ff","timeToRead":1,"slug":"project/project2/project2","frontmatter":{"title":"Smart POS Web App","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["React","NextJS","Tailwind","Firebase","Firestore","NodeJS","OpenShift"],"description":null,"date":null}},{"id":"63959d00-7675-5872-abd4-3ace45480a22","timeToRead":1,"slug":"project/project9/project9","frontmatter":{"title":"Budget Calculator","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"57e4f42a-2bfd-5fde-b040-2907d11a5ea5","timeToRead":1,"slug":"hero/hero","frontmatter":{"title":"Danniel Hansel","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":null,"description":null,"date":null}},{"id":"e8a491a4-73b5-5be8-b294-49362cf66dc0","timeToRead":1,"slug":"project/project3/project3","frontmatter":{"title":"E-Commerce Web App","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["React","Material UI","Commerce.js","Stripe"],"description":null,"date":null}},{"id":"0f9e61b3-88a9-5ea1-b965-0098a1061015","timeToRead":1,"slug":"project/project4/project4","frontmatter":{"title":"Type Racer","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","Bootstrap"],"description":null,"date":null}},{"id":"1811b711-5e38-548f-ad4e-5e774b0f2a00","timeToRead":1,"slug":"project/project11/project11","frontmatter":{"title":"Accordion UI","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"a4e7f4fe-a19d-5cf5-86fd-149edddafdc3","timeToRead":1,"slug":"project/project6/project6","frontmatter":{"title":"Todos App","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"875cf1c0-a200-5715-9d26-d0cdd74aea7b","timeToRead":1,"slug":"project/project8/project8","frontmatter":{"title":"Quote Generator v2","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"c34b3f70-bf92-5a5f-9d18-90fb40c407aa","timeToRead":1,"slug":"project/project5/project5","frontmatter":{"title":"Tic Tac Toe","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}},{"id":"d6c51e86-ed84-5489-a9f8-0f38e78963b2","timeToRead":1,"slug":"project/project7/project7","frontmatter":{"title":"Quote Generator v1","author":null,"bannerUrl":null,"bannerCredit":null,"slug":null,"tags":["Vanilla JS","HTML/CSS"],"description":null,"date":null}}]}},"pageContext":{"id":"6716a85b-6801-525e-b2ea-5448c01bf60d"}},
    "staticQueryHashes": ["2744905544","3145194271","3970664207"]}