<?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: Christian von Uffel</title>
    <description>The latest articles on DEV Community by Christian von Uffel (@christianvonuffel).</description>
    <link>https://dev.to/christianvonuffel</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%2F501683%2F206ede0a-7935-47ca-b46a-63969435d336.jpeg</url>
      <title>DEV Community: Christian von Uffel</title>
      <link>https://dev.to/christianvonuffel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/christianvonuffel"/>
    <language>en</language>
    <item>
      <title>Why People Designing Websites with Standard CSS Should Switch to Tailwind</title>
      <dc:creator>Christian von Uffel</dc:creator>
      <pubDate>Fri, 09 Apr 2021 22:09:26 +0000</pubDate>
      <link>https://dev.to/christianvonuffel/why-people-designing-websites-with-standard-css-should-switch-to-tailwind-2afo</link>
      <guid>https://dev.to/christianvonuffel/why-people-designing-websites-with-standard-css-should-switch-to-tailwind-2afo</guid>
      <description>&lt;p&gt;When I decided to teach myself Tailwind it was mostly because I had become frustrated with the standard CSS framework.&lt;/p&gt;

&lt;p&gt;I was building websites using standard CSS, but I was getting annoyed trying to set up responsive design properties and found myself jumping back-and-forth between my HMTL and CSS files to make sure I was connecting the right properties to the right elements.&lt;/p&gt;

&lt;p&gt;Working with standard CSS was cumbersome and I knew there had to be a better way.&lt;/p&gt;

&lt;p&gt;In my process of learning standard CSS, I had heard about Tailwind several times before. It was touted as the next new thing and while I had heard it spoken about only positively I had also learned to heed other programmers advice, which is to be wary of investing in new frameworks.&lt;/p&gt;

&lt;p&gt;As I have learned, frameworks can be mirages of added productivity; things that look great from afar, but once you begin to actually put in the effort and use them realize that they offer no material value.&lt;/p&gt;

&lt;p&gt;Well, I’m here to tell you that Tailwind is not one of those frameworks lacking real material value. I enjoy using it myself. Not because I have to, but because I find it really useful while working on small projects.&lt;/p&gt;

&lt;p&gt;Here's what Tailwind does for me that makes me find it so useful:&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind helps me keep my creative momentum going when I create and design elements.
&lt;/h2&gt;

&lt;p&gt;Normally, when I'm creating HTML and CSS I have to think about them abstract from each other and then connect them using an additional number of steps.&lt;/p&gt;

&lt;p&gt;I need to think of class names and I need to organize CSS properties in different sections of the CSS file so it looks good on both desktop and mobile devices.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#tagline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;192px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;64px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;640px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;414px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;#tagline&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;128px&lt;/span&gt;&lt;span class="p"&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;I need to go back and forth between adjusting CSS class properties and seeing how content looks in my browsers.&lt;/p&gt;

&lt;p&gt;Making adjustments to my content and its style in different files makes it harder for me to mentally keep track of the changes, stay organized, and designing quickly.&lt;/p&gt;

&lt;p&gt;Small additional steps in my code’s organization and holistic thought process cause me to lose momentum.&lt;/p&gt;

&lt;p&gt;Contrast that with working with Tailwind.&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"max-w-screen-sm text-center pt-32 sm:pt-48 sm:pb-16"&lt;/span&gt;&lt;span class="nt"&gt;&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;In Tailwind, I think about what I want to create and design it in the flow. I don’t need to come up with CSS class names and ids. I don’t need to search for CSS class and id names to adjust the appropriate property of a global element, or then have to worry about if I’ve made a change that will break how something else works.&lt;/p&gt;

&lt;p&gt;Now if you normally implement your web designs using standard CSS, you may be wondering how Tailwind is different from in-line styles.&lt;/p&gt;

&lt;p&gt;The answer is that in-line styles don't allow you to include responsive media queries, meaning that in traditional CSS you are forced to use media queries by declaring them in your CSS.&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/cvonu/embed/RwKxKPO?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;But of course, you also know if you use media queries that the class names and ids must also then be duplicated into separate sections which then prevent you from seeing both desktop and mobile device settings in a single view.&lt;/p&gt;

&lt;p&gt;Of course, this separation between desktop and mobile within your design thought process poses a very significant problem.&lt;/p&gt;

&lt;p&gt;Without having an easy way to see both types of devices style code, you’ll likely be spending more time and effort testing your website or application’s front-end design.&lt;/p&gt;

&lt;p&gt;For me, that would mean spending more time in the responsive design tool of Mozilla’s developer edition browser, but for you, that may require testing on multiple browsers including, god forbid, Internet Explorer.&lt;/p&gt;

&lt;p&gt;So if you're using standard CSS you have to jump around inside of the CSS file to see how the design is connected to your content.&lt;/p&gt;

&lt;p&gt;In Tailwind, you can see how content is designed for different screen sizes directly simply by reading the class names of the content itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trade-offs of using Tailwind
&lt;/h2&gt;

&lt;p&gt;Using Tailwind requires you to have a decent understanding of CSS to get fully up and running.&lt;/p&gt;

&lt;p&gt;People who are new to CSS may not feel comfortable using Tailwind, just like they might have difficulty designing standard websites from scratch.&lt;/p&gt;

&lt;p&gt;Tailwind uses different syntax than standard CSS to declare style properties. This syntax is based on standard property names and attempts to be both shorter and more readable, however, you’ll still need to learn this new set of syntax to implement Tailwind into your designs.&lt;/p&gt;

&lt;p&gt;Luckily, for people who are looking to transition to using Tailwind, you'll be pleased to hear that Tailwind has some of the best documentation of any framework on the Internet.&lt;/p&gt;

&lt;p&gt;As cumbersome as it might be to read the documentation for different JavaScript methods on Mozilla’s MDN, the experience of reading the documentation for Tailwind is a polar opposite.&lt;/p&gt;

&lt;p&gt;In every possible example I have found, searching how to implement a specific CSS property in Tailwind has resulted in me finding a well written and accessible example of both the style being implemented in practice and exactly how I can implement it myself.&lt;/p&gt;

&lt;p&gt;Unlike other framework’s homework-like documentation, Tailwind’s documentation is a pleasure to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shortcomings of using Tailwind
&lt;/h2&gt;

&lt;p&gt;Just because Tailwind is a CSS framework I find extremely useful doesn't mean that it doesn't have some drawbacks.&lt;/p&gt;

&lt;p&gt;You will find yourself creating custom CSS to implement typography and implement global values if you have established brand guidelines, color values, and non-standard element properties.&lt;/p&gt;

&lt;p&gt;If you’re creating blog content and long-form writing, you will instantly be struck by Tailwind’s complete reset of HTML element design, which renders your previously easy and repetitive use of standard HTML elements to style your articles and long-form content useless.&lt;/p&gt;

&lt;p&gt;Of course, you could recreate your styles using custom CSS again, but thankfully the team behind Tailwind has heard its users' repeated cries and created a solution: Tailwind Typography.&lt;/p&gt;

&lt;p&gt;Tailwind’s Typography plugin lets you style content using standard HTML elements like you’re used to. All you need to do is install the plugin and declare "prose" as a class property before you can start writing like you used to. So if you were worried about having to style every header tag, fret not.&lt;br&gt;
Another shortcoming of Tailwind is if you’re mindful of performance, specifically data and speed.&lt;/p&gt;

&lt;p&gt;Tailwind's CSS package is large. The package size of loading the entire library into your site according to Tailwind is 45.2kB compressed and 1941.7kB raw.&lt;/p&gt;

&lt;p&gt;That’s a pretty hefty file to ask users to load before they can see your site’s content. However, as Tailwind’s team and documentation will readily tell you, this size is not representative of Tailwind’s true file size.&lt;/p&gt;

&lt;p&gt;That’s because when you’d be using Tailwind within a production-ready application you wouldn’t need to include the thousands of utility classes that Tailwind offers as options, but instead can shed off the vast majority of its size so you would only use the tiny fraction being utilized on your site.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>design</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>3 Things I Learned Recreating Stripe's Pricing Page</title>
      <dc:creator>Christian von Uffel</dc:creator>
      <pubDate>Thu, 04 Feb 2021 06:34:29 +0000</pubDate>
      <link>https://dev.to/christianvonuffel/3-things-i-learned-recreating-stripe-s-pricing-page-3ga1</link>
      <guid>https://dev.to/christianvonuffel/3-things-i-learned-recreating-stripe-s-pricing-page-3ga1</guid>
      <description>&lt;h3&gt;
  
  
  Check out the project:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://gallant-bose-76c7bd.netlify.app/recreations/stripe/" rel="noopener noreferrer"&gt;My Recreation of Stripe's Pricing Page&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Compare it to the original:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stripe.com/pricing" rel="noopener noreferrer"&gt;Stripe's Pricing Page&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  SVG offers animation and design advantages beyond performance
&lt;/h2&gt;

&lt;p&gt;Most people know using SVG is a great way to save on performance for the loading time of your website.&lt;/p&gt;

&lt;p&gt;One thing you may not know however is that SVG icons can easily be styled and animated in ways other image formats may not.&lt;/p&gt;

&lt;p&gt;You can fill the color of SVG image icons using CSS' background clip property.&lt;br&gt;
&lt;iframe height="600" src="https://codepen.io/cvonu/embed/ZEBbqwL?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;br&gt;
You can also animate SVG images by morphing the SVG image's path on hover state.&lt;/p&gt;
&lt;h2&gt;
  
  
  It's easier to use absolute and relative positioning to create background element layouts than adjusting z-index values
&lt;/h2&gt;

&lt;p&gt;Stripe's pricing page, like many webpages, uses background layouts to add visual flair without distracting users from important customer messaging.&lt;/p&gt;

&lt;p&gt;These background elements can be easy to create when they're composed of simple background color transitions, full-page cover images, and hero patterns, but when the background is itself composed of grid elements developers need a slightly more detailed understanding of how to use and implement absolute and relative positioning.&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="c"&gt;&amp;lt;!-- background color grid --&amp;gt;&lt;/span&gt;
&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;"relative min-h-screen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &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;"absolute inset-0 transform -skew-y-12 origin-top-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &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-green-100 grid grid-cols-10 grid-rows-6 min-h-screen bg-gradient-to-r from-green-400 to-green-200 transform"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &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-green-200 opacity-50 row-start-3 col-span-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &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-green-100 opacity-50 row-start-5 col-start-9 col-span-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/div&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;h2&gt;
  
  
  Deeper appreciation for purposeful simplicity in design and engineering
&lt;/h2&gt;

&lt;p&gt;While I was doing research on Stripe's design and engineering I came across great content on their blog.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stripe.com/blog/connect-front-end-experience" rel="noopener noreferrer"&gt;Connect: behind the front-end experience&lt;/a&gt; offered many insights.&lt;/p&gt;

&lt;p&gt;Some of my key takeaways:&lt;/p&gt;

&lt;p&gt;Stripe's team uses CSS instead of image files to render how Stripe's platform looks on devices to reduce file sizes and increase performance beyond even what efficient image file formats like SVG offer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"We can add hardware-acceleration, animate any part, make it responsive without losing image quality, and precisely position DOM elements (e.g. other images) within the laptop’s display. This flexibility doesn’t mean giving up on clean code—the markup stays clear, concise and descriptive"&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"laptop"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"shadow"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"lid"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"camera"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"screen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chassis"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"keyboard"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"trackpad"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/span&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;&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%2Fi%2Fcn2qiwx5fpdxc2l8bjik.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%2Fi%2Fcn2qiwx5fpdxc2l8bjik.png" alt="Stripe's Laptop Graphic composed from CSS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Descriptions of tradeoffs between different types of web animation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"CSS transitions. This is the fastest, easiest, and most efficient way to animate. For simple things like hover effects, this is the way to go."&lt;/p&gt;

&lt;p&gt;"Web Animations API...This should be your default choice for any animation where you need interactivity, random effects, chainable sequences, and anything richer than a purely declarative animation."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  A few other Stripe articles I enjoyed reading:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://stripe.com/blog/globe" rel="noopener noreferrer"&gt;To design and develop an interactive globe&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The most straightforward way to animate individual dots is to generate them in a three-dimensional space. To do this, we reused the code from our SVG to generate rows of dots as geometry in Three.js. Each row includes a different number of dots, from zero at the poles to five hundred at the equator. We used a sine function to choose the number of dots for each row, plotted each dot, and applied the lookAt method to rotate each dot to face the center of the sphere. However, the number of dots jumped inconsistently along a few latitudes, creating harsh lines and an unnatural effect in the longitudinal columns."&lt;/p&gt;

&lt;p&gt;"we turned off the antialias parameter of the WebGL renderer. This one change not only fixed the issue on high-res monitors, but also improved performance of the animation and smoothness of scrolling on all devices, even those already running at 60fps. One might assume that removing antialiasing would make everything look pixelated. Since it only applies to the edges of the geometry, our image textures were still smooth and gradients and lighting were unaffected."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://stripe.com/blog/accessible-color-systems" rel="noopener noreferrer"&gt;Designing accessible color systems&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"the way HSL calculates lightness is flawed. What most color spaces don’t take into account is that different hues are inherently perceived as different levels of lightness by the human eye—at the same level of mathematical lightness, yellow appears lighter than blue."&lt;/p&gt;

&lt;p&gt;"When we take a sample of colors with the same lightness and saturation in a perceptually uniform color space, we can observe a significant difference. These colors appear to blend together, and each color appears to be just as light and as saturated as the rest."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://stripe.com/blog/teaching-employees-to-code" rel="noopener noreferrer"&gt;How Stripe teaches employees to code&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It’s easy for familiarity with code to become a barrier between different groups within a technology company: lots of companies have an upper tier of code-wrangling wizards that are supported by the rest of the company, sometimes known as the non-engineers. From the beginning, we’ve tried hard to avoid this at Stripe. In seating, we mix engineering teams with non-engineering teams. When we hire, we seek out engineers who are excited about problems beyond code itself."&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>webdev</category>
      <category>showdev</category>
      <category>tailwindcss</category>
      <category>css</category>
    </item>
    <item>
      <title>Recreating Notion's Homepage with Tailwind CSS and Vue JS</title>
      <dc:creator>Christian von Uffel</dc:creator>
      <pubDate>Mon, 25 Jan 2021 20:23:48 +0000</pubDate>
      <link>https://dev.to/christianvonuffel/recreating-the-homepage-of-a-billion-dollar-business-with-tailwind-css-and-vue-js-1648</link>
      <guid>https://dev.to/christianvonuffel/recreating-the-homepage-of-a-billion-dollar-business-with-tailwind-css-and-vue-js-1648</guid>
      <description>&lt;h2&gt;
  
  
  View the Project:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://gallant-bose-76c7bd.netlify.app/recreations/notion/" rel="noopener noreferrer"&gt;My Recreation of Notion's Homepage&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare it to the Original
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.notion.so/product" rel="noopener noreferrer"&gt;Notion's Homepage&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Deciding what to build to showoff my front-end skills
&lt;/h1&gt;

&lt;p&gt;When I first decided to build something &lt;del&gt;for the Digital Ocean Hackathon&lt;/del&gt; to show off my front-end webdev skills, I asked myself "What would be useful for a real business?"&lt;/p&gt;

&lt;p&gt;The answer I came to is recreating the website of a real business, a business whose website is so important to them that it serves as a foundation of how they do business and serve their customers.&lt;/p&gt;

&lt;p&gt;The first criteria I had was obvious to me: the business whose website I chose to recreate had to be huge, or at least hugely valuable.&lt;/p&gt;

&lt;p&gt;The second criteria was less obvious: the business' website had to not depend on the use of outside assets and graphics to make it look nice. Pretty assets don't show off my front-end skills and don't show off how I can best help businesses.&lt;/p&gt;

&lt;p&gt;So I wanted to recreate an existing successful business' website that uses a variety of CSS skills: flexbox, grid, and a variety of styles for images, text, and a lot of data that needed to be managed in a robust way.&lt;/p&gt;

&lt;p&gt;After all, part of the reason I decided to recreate a serious internet business' homepage, is that I wanted to improve my front-end webdev process and this offered me the perfect challenge: totally doable, yet more complicated than any page I've created before.&lt;/p&gt;

&lt;p&gt;I looked at a few sites before I chose one:&lt;/p&gt;

&lt;p&gt;First I looked at Nike because I like their branding, but after looking at their website, I realized most of my work recreating it would just be copying their media assets. &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%2Fi%2F3n5qzpb45gjlklfieqxa.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%2Fi%2F3n5qzpb45gjlklfieqxa.png" alt="Nike's Homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sure, I could recreate their navigation menus using flexbox and product displays using grid, but most of my work wouldn't show through.&lt;/p&gt;

&lt;p&gt;Second, I looked at Stripe. Stripe's website is beautiful, but boy is it complicated and, secondly, it has the same problem as Nike: recreating Stripe's website depends on using a lot of outside assets, except it's worse! Stripe's website uses assets that are harder to access and implement.&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%2Fi%2F9fkd88qy4i4d5kz1tt1o.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%2Fi%2F9fkd88qy4i4d5kz1tt1o.png" alt="Stripe's Homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Still, Stripe's website uses some pretty cool layout designs I could recreate using grid. Maybe this is something I'll revisit later.&lt;/p&gt;

&lt;p&gt;Lastly, I looked at Notion. Notion's website, like their application, is beautiful, friendly, and accessible. It uses a bunch of assets, but, unlike Stripe and Nike's websites, doesn't rely on them. It uses modern CSS skills like flexbox and grid and a lot of text data that's managed best dynamically using components.&lt;/p&gt;

&lt;p&gt;Notion's homepage was the clear and obvious winner.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Process
&lt;/h2&gt;

&lt;p&gt;One thing I decided early on was that I wasn't going to look at the original webpage's code. If someone wants to hire me to create a website for them, I don't have any starting code to work with so I'm not going to use that here either. They'll simply hand me off some wireframes from Figma or Sketch with the assets I need and/or a validated product spec.&lt;/p&gt;

&lt;p&gt;I recreated all the page's designs and layout by sight.&lt;/p&gt;

&lt;p&gt;No inspecting code, no copying code. All translating what I see into what write.&lt;/p&gt;

&lt;p&gt;For me, there's only one good solution for this "what you see is what you code" sort of webdev framework and that's &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tailwind is great because it removes the layer of abstraction and lock-in that makes global CSS so unmanageable.&lt;/p&gt;

&lt;p&gt;Next, there's data. All the data serious internet business websites use is managed dynamically using components.&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="c"&gt;&amp;lt;!-- testimonials section --&amp;gt;&lt;/span&gt;
&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;"grid md:grid-cols-2 lg:grid-cols-3 gap-12 md:gap-16 p-8 md:p-16 mx-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"testimonial in testimonials"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-gray-100 rounded-lg border border-gray-100 hover:border-gray-300 p-4 flex flex-col items-start"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"testimonial.companyLogo"&lt;/span&gt; &lt;span class="na"&gt;:alt=&lt;/span&gt;&lt;span class="s"&gt;"testimonial.sourceTitle"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-12 object-contain object-left overflow-hidden"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &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;"text-lg my-6 h-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            "{{testimonial.content.trim()}}"
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &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;"text-sm flex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            {{testimonial.source}}
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &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;"text-sm text-gray-700 capitalize"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            {testimonial.sourceTitle}}
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/a&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;You alter design and data using two separate processes which keep both safe from accidental changes to each other.&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="err"&gt;testimonials:&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="err"&gt;companyLogo:&lt;/span&gt;&lt;span class="s2"&gt;"images/blinkist.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;content:&lt;/span&gt;&lt;span class="s2"&gt;"On notion, everything is in one place and everyone can find what they need on their own. We have cut down on interruptions, and stayed more focused on priorities."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;source:&lt;/span&gt;&lt;span class="s2"&gt;"Milica Radojevic"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;sourceTitle:&lt;/span&gt;&lt;span class="s2"&gt;"People experience partner, Blinkist"&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="err"&gt;companyLogo:&lt;/span&gt;&lt;span class="s2"&gt;"images/figma.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;content:&lt;/span&gt;&lt;span class="s2"&gt;"Notions ease-of-use is one of its hallmarks. It helps you visually navigate contact and remember where something is."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;source:&lt;/span&gt;&lt;span class="s2"&gt;"Marie Szuts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;sourceTitle:&lt;/span&gt;&lt;span class="s2"&gt;"Head of people ops, Figma"&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="err"&gt;companyLogo:&lt;/span&gt;&lt;span class="s2"&gt;"images/duolingo.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;content:&lt;/span&gt;&lt;span class="s2"&gt;" we wouldn't be able to customize our workflow like this in any other product"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;source:&lt;/span&gt;&lt;span class="s2"&gt;"Justin Goff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;sourceTitle:&lt;/span&gt;&lt;span class="s2"&gt;"product manager, duolingo"&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="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Components let you update how data's displayed across your website without updating individual pages one by one.&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%2Fi%2F7m6nhvd1xwc22l1hss73.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%2Fi%2F7m6nhvd1xwc22l1hss73.png" alt="Testimonials on Notion's Homepage"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Avoiding code duplication helps you avoid making errors that make your website harder to manage, less friendly to use, and less focused on satisfying your users.&lt;/p&gt;

&lt;p&gt;I manage the webpage's data using &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue JS&lt;/a&gt;. Its fast modern framework makes managing data easy and reliable.&lt;/p&gt;

&lt;p&gt;But there's one problem with Vue JS and that's SEO.&lt;/p&gt;

&lt;p&gt;Vue JS, like React and Angular, render a webpage's content dynamically, so they're not good for SEO.&lt;/p&gt;

&lt;p&gt;To solve this problem, my next steps are rebuilding this site &lt;br&gt;
using &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;NUXT JS&lt;/a&gt; which builds static HTML pages to get all the benefits of dynamic rendering and component organization from Vue JS with all the SEO benefits of static HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS Properties I Learned
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;pointer-events-none
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Makes images non-draggable&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS Properties I knew, but hadn't used before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;flex-row-reverse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for conditionally reversing the orientation of your footer elements on mobile, such as when you want to show a copyright notice on the left in your footer on desktop, but below everything else on mobile.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>css</category>
      <category>vue</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
