8000 GitHub - TomasHubelbauer/hn-tailwind: Hacker News redesigned using Tailwind for practice
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

TomasHubelbauer/hn-tailwind

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hacker News Tailwind

Note: This readme is not a structured document, it is a chronological record of the work presented herein and is more or less append-only. Be aware.

I want to learn Tailwind and in order to do it in a practical way, I am going to clone Hacker News and see how it goes. I might clone more websites next.

I am using the official Tailwind site as a resource: https://tailwindcss.com/

I am not using any other framework in combination with Tailwind now so I'll use the CLI to compile Tailwind to the final CSS. Other ways to use Tailwind are:

  • PostCSS - a plugin which gets invoked by PostCSS which itself is ran by a framework it is integrated in
  • Framework-specific integration - when using a framework but not PostCSS
  • PlayCDN - use a script tag and try out Tailwind in a development setting

Since I am sticking with the CLI, the first step is to install it:

npm install --global tailwindcss

On macOS, with Node (and NPM) installed using the Node installer (my preferred method) as opposed to NVM or some other tooling manager (e.g.: Turbo), file permissions are set up in a way that will cause an error unless changed.

This behavior is IMO stupid and I'd argue things should work out of the box, but nonetheless, that's where we are. To fix the permissions, run:

sudo chown -R tomashubelbauer: /usr/local/lib/node_modules

In many cases, you'll want to install Tailwind as a development dependency or use NPX to call it. I don't use it for any other projects checked out on my machine and I want this project to always use the latest version so I will install it globally and I'll keep the globally installed version current.

Tailwind CLI even when installed globally won't export a binary executable to call by name right away, it still needs to be called using NPX, it just won't be taken from the repository scope, but instead from the global scope.

To verify that works, the --help option can be used. Note that the Tailwind CLI doesn't provide a version command or --version option.

npx tailwindcss --help

I am using Tailwind 3.2.4 at the time of writing. My versions of Node and NPM are 19.1.0 and 8.19.3, respectively.

To actually install and configure Tailwind to this repository, the init CLI command is used:

npx tailwindcss init

This will drop a configuration file named tailwind.config.js to the directory and this file will be picked up and used when the CLI determines what files to check for Tailwind classes and where to put the output, stuff like that.

It looks like this:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [],
  theme: {
    extend: {},
  },
  plugins: [],
}

So far, I am not loving the fact that the Tailwind CLI is named tailwindcss and not just tailwind. It is too much to type! Also, not a fan of the old-school module approach in the configuration file. It is almost 2023 and the configuration file really should be using ESM IMO.

The configuration file should also come with a default content value that picks up index.html. That would be a very weekly opinionated default, better than an empty value. I tried to see if there is an undocumented implicit default by running just npx tailwindcss but I got yelled at for not specifying --input.

Another thing, and this is not necessarily something I mind, but it is curious how often you see "configuration" files which are just code files. Of course, this is nothing new, WebPack does it, too, and Pulumi is basically built on top of this idea. It doesn't feel obviously good to me, but I don't think it is bad either.

Anyway, using npx tailwindcss --input index.html goes through but since I did not specify --output, I get no output. Not to mention that as of now, index.html is empty.

At this moment I am confused as to why I need to use --input when I have the configuration file.

Curiously, using npx tailwindcss --watch and I do not need to specify the --input option. I think there are multiple entrypoints to the CLI but its interface, the help output or the quickstart documentation don't make this obvious or discoverable.

In general, the installation documentation seems to end mid-way. https://tailwindcss.com/docs/installation

I would have expected it to show how to set up the configuration file so that the awkward CLI command can be reduced to something reasonable.

I'll try to put this together myself. With the default configuration and the --watch option, I get no transpilation as there is no input to speak of to transpile, and I get the result at the CLI output.

A good first step then seems to figure out how to use the configuration to specify the output. Let's take a look at the configuration documentation. https://tailwindcss.com/docs/configuration

Amazingly, this does not seem to be possible at the moment! tailwindlabs/tailwindcss#5033

Between specifying --output index.css and > index.css I think I will prefer the latter as it is shorter.

Tailwind really seems gearer towards integration with other pieces of what many call the modern web development stack which means the DX of using it standalone suffers as a result of less attention to the use-case.

I will factor out the CLI command to its own shell file and run it instead of typing it out each time, but I really would like to be able to just run tailwindcss (or better yet, tailwind), and have the right thing happen.

echo "npx tailwindcss > index.css" > run.sh
chmod +x run.sh
./run.sh

I will switch to using the --watch option later (probably will add it to this shell script), but for now I want to be deliberate with when I run the compile step.

The installation documentation page doesn't mention this explicitly, but it nudges you to name your CSS entry-point input.css. I will treat this as a Tailwind best practice and adopt this standard.

The next step is to import the Tailwind directives in the main CSS file:

@tailwind base;
@tailwind components;
@tailwind utilities;

I am curious as to why the non-CSS keyword @tailwind was chosen over something like @import 'tailwind:…' which would be as unique and recognizable to the TW compiler as @tailwind is, but wouldn't cause the default VS Code CSS parser to report a warning at this unknown directive.

With the input and output configured, I can start authoring my Tailwind-enhanced HTML. The output file will be index.css so let's reference it in the HTML template: And to make sure it really works, let's adorn the HTML body with the Tailwind font-bold utility class.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hacker News</title>
    <link href="index.css" rel="stylesheet" />
  </head>
  <body class="font-bold">
    Hello, world!
  </body>
</html>

After running ./run.sh and opening index.html in the browser (e.g. by running open index.html), we see that nothing actually happens! Or rather, it is apparent that Tailwind is working somewhat on the page, as the default browser margin is reset. But our text is not bold and looking through the compilation target index.css there is no hint of font-bold at all.

Is font-bold not in @tailwind base;? The problem lies elsewhere, as is helpfully reported by the Tailwind CLI. Despite our use of the font-bold helper class, it still reports that it did not find any Tailwind utility classes in the input.

And indeed I never set this to anything, I only complained it doesn't seem to default to anything, even implicitly. That's confirmed now, so let's set it to index.htm explicitly and 7CA6 try again.

This time, ./run.sh went through without that warning and we indeed do see a bold span in the page as rendered by the browser. At least HTML inputs are supported! The documentation provides an example where a CSS input is used instead.

This should be enough to be able to put together a simple development loop of edit, compile, test.

Let's start building Hacker News, then! First, let's block out the major landmarks of the site. We have the centered column containing the whole of the content. We have the top menu row with the link navigation and optionally, the logged in user controls. We have the list of links and their associated controls. And lastly, we have the footer with more links and the search field.

In terms of the main body wrapper, I want to center it relative to the viewport, and one of the ways to do this is to make the body element a flex container. Then, the content container can be centered using justify-content: center. A quick helping of <body class="flex justify-center"> will make this happen for us.

To give the main container a size relative to the viewport, it seems one of the container classes in Tailwind will be a way to go. Let's go with lg, the 1024px breakpoint. It seems it needs to be used in conjunction with container, so: <div class="container lg">.

Resizing the browser window, it seems we do get some built-in breakpoints and the container resizes and accomodates to fit the viewport width.

I think it is time to turn on --watch now as I've already forgotten to run ./run.sh a couple of times and then was bamboozled as to why my changes were not working.

Funnily enough, lg matches the width of the Hacker News main body almost exactly at my breakpoint when the browser is maximized. I will decide later on whether I want to go for a pixel-perfect copy or just an approximation which won't look exactly like Hacker News but will be nice in terms of the Tailwind classes and how I use them. I am already leaning towards the latter.

Let's block out the main menu, the link list and the footer now. I have only added the container divs and a few links for now. The link list is an ol and I found that list-decimal is the way to make it show the numbers.

By default even unordered lists do not show the list points in Tailwind.

amber-50 was the closest color from the Tailwind built-in colors to approximate the Hackew News background. Funnily enough the site is mockingly called "the Orange Site" yet orange-50 wasn't the right fit here. I am sure it will redeem itself when I go coloring the main menu. Since this was for a background color, I needed to prefix the color with bg-.

To get the body margin (which Tailwind zeroes by default) back, I used m-2 on the body. It seems to match HN's pretty closely.

Now for the header background color. I found that orange-500 matches the Hacker News color almost perfectly so I guess the site did redeem itself, indeed!

My menu is two-rows now because I don't have the right-float items figured out yet. A "float" is an old-school way of saying I need to make it a flex container and put an automatic margin on the last item.

At this point I am slowly but surely starting to get why people like Tailwind. Prototyping this site is fast so far. Granted, Hacker News is a simple site and it wouldn't be all that slower without Tailwind, but I do feel the power of fast prototyping on my fingerprints using it and that's a good sign!

The first menu link (the Hacker News "logo" link) needs to be bold and a bit larger. Since the menu is a flex container now, I can also introduce gaps between the items so that aren't as crowded as they are without.

Initially I thought I would set the logo graphic as a background image of the Hacker News logo link, but real HN uses an image for it and it seemed easier to do the same thing to not overcomplicate the utility classes.

I downloaded the image off HN to the repository because it seems to load super slowly or maybe it was just Firefox being weird on me.

Turns out to do a 1-pixel wide border, border is the way to go, not border-1 which surprised me but I think it makes sense. Maybe border-1 should print a warning? One would think this would be a common mistake.

I put the image into the logo link so it is clickable as well. Unfortunately, this made the logo link break into two rows. I messed around with whitespace-pre but that blew up the logo because there is whitespace before the img (I think). I settled on using flex with a nested gap.

I put a padding on the menu row to match the HN spacing. 0.5 looked best but I was disappointed to learn I can't do p-.5, have to do p-0.5.

With the logo being a flex container the inline links in the rest of the menu look off vertically now so I need to align the menu row flex items centerwise as well.

The link text font size was matched using text-sm. That looked good.

The "logout" item is weird. It seems to stick to the end of the row, not respecting the padding. And it should be padded more according to the HN template, so I tried using pr-2 on the menu row to no avail.

I still need to figure this out.

The rough next steps:

  • Build in GitHub Pages CI and deploy the Tailwind artifact I have decided to enable GitHub Pages but I don't want to commit the output.
  • Use the logo for the tab icon as well
  • Figure out the "logout" item right padding from parent not being respected
  • Mark the "news" item as active using the light color
    • Consider expanding this to :target and pure-CSS tabs
  • Look into VS Code Tailwind extension for utility class auto-complete
  • Figure out the list item numbers being outside of the area by default
  • Expand the list items to have the control links and other details
    • Consider generating these dynamically This might make the previewing/testing experience a bit slower so be aware.
  • Figure out why Firefox is laggy on this file - is it the watcher?
    • Try working with the watcher off to see if it is access race Maybe my browser refresh comes too early while the file is still being compiled or written by the watcher.
    • Consider using VS Code extension to have the browser page side by side I could side-step this whole issue by trying this out. There should be non-localhost based preview extensions hopefully.
    • Consider figuring out Tailwind hot reload or generic hot reload This would solve potential file access race issue if it is that.
  • Design the list items
  • Design the footer items
  • Consider also designing the discussion tree for practice/experience
  • Consider hooking this up to the Hacker News API for live data This would make the list load with a delay so might interfere with iteration speed while testing manually.
    • Consider hosting a GitHub Pages version to be able to use read-only

About

Hacker News redesigned using Tailwind for practice

Topics

Resources

Stars

Watchers

Forks

0