Skip to content

devproca/tailwind-dev-day

Repository files navigation

When we write html and css, it's common to have to jump back and forth between css and html files to get an understanding of what's going on. This is most apparent when global styles are used - we find ourselves in multiple css files, our html and in the browser inspector trying to figure out what's going on. Wouldn't it be nice to make the change in one place?

Bootstrap 4 was one of the first frameworks to introduce a small set of utility classes. The problem with an incomplete set of utility classes is that you'll find yourself writing regular css and using the utility classes, which means you're still bouncing between files.

Then along came Tailwind! Tailwind is a css utility framework that lets you write your html without ever leaving that file.

Some advantages are:

  • No need for other css frameworks and color variables to have consistent colors throughout your application
  • Easy to create consistent spacing throughout your application

Using tailwind with angular

This dev day is tested for angular 10. It is recommended you use the latest angular 10 cli. If you wanted to use angular 11 setup instructions can be found here.

npm uninstall -g @angular/cli
npm cache clean
npm install -g @angular/cli@^10

Setting up an angular application configured to use tailwindcss

NOTE: These instructions are just for setting up tailwind in a new project; This is not needed to do the exercises. Tailwind will be setup correctly on all the exercise branches referenced below. If you're just working through the exercises skip ahead to exercise 1

Skip the install because we will use yarn instead of npm

ng new --skip-install angular-tailwind
cd angular-tailwind
yarn install

Add some additional dependencies and configure

ng add ngx-build-plus
yarn add --dev tailwindcss autoprefixer postcss postcss-import postcss-loader postcss-scss

Add a custom webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
        options: {
          postcssOptions: {
            ident: 'postcss',
            syntax: 'postcss-scss',
            plugins: [
              require('postcss-import'),
              require('tailwindcss'),
              require('autoprefixer'),
            ],
          },
        },
      },
    ],
  },
};

Edit the angular.json to reference your webpack config. You'll need to do this in the build, serve, and test sections.

...
options: {
  "extraWebpackConfig": "webpack.config.js",
...
}
...

Generate the tailwind config

npx tailwind init

Configure the purge option in the newly generated tailwind.config.js. This will configure tailwind to eliminiate any unused utility classes in the build process.

**Note: When your application is built without the purge option, your styles will be approximately 3MB. Running with purge enabled can slow down local development and reload times however.

purge: {
  enabled: true,
  content: [
    './src/**/*.html',
    './src/**/*.scss'
  ]
},

To your styles.scss add

@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

Edit your app.component.html

<div class="m-10">
  <div class="rounded border border-gray-300 p-4 flex">
    hello tailwind
  </div>
</div>

Start up your application!

yarn start

Exercise 1 - flex refresher

This section is optional if you're already familiar with flex. We're not going to cover flex in depth, but only how to horizontally and vertically align elements in a flex row.

git checkout 1a-start

Tailwind has the following utility classes that you'll need. In a flex row, they behave as follows:

  • items-start (vertically position top - this is the default so you won't need to write it)
  • items-center (vertically position center)
  • items-end (vertically position bottom)
  • justify-start (horizontally position at start - this is the default so you won't need to write it)
  • justify-center (horizontally position center)
  • justify-end (horizontally position bottom)

When you load the application, there is a red square displayed in a blue square.

1a. vertically and horizontally center the red square inside the blue square.

Answer

<div class="m-10">
  <div class="h-80 w-80 bg-blue-500 flex items-center justify-center">
    <div class="h-20 w-20 bg-red-500"></div>
  </div>
</div>

1b. vertically center the red square inside the blue square. horizontally the red square should be at the start

Answer

<div class="m-10">
  <div class="h-80 w-80 bg-blue-500 flex items-center">
    <div class="h-20 w-20 bg-red-500"></div>
  </div>
</div>

1c. vertically center the red square inside the blue square. horizontally the red square should be at the end.

Answer

<div class="m-10">
  <div class="h-80 w-80 bg-blue-500 flex items-center justify-end">
    <div class="h-20 w-20 bg-red-500"></div>
  </div>
</div>

Exercise 2 - make a chip component

Chips are compact elements that represent an input, attribute, or action. Let's make one

git checkout 2-start

To make a chip we'll break it up into 2 steps.

  • create an avatar component
  • create an svg button component
  • create the chip component

2a. Use tailwind html classes to create an avatar component (don't write things in any scss files).

ng g c avatar

avatar.component.ts

import {Component, Input} from '@angular/core';

@Component({
  selector: 'app-avatar',
  templateUrl: './avatar.component.html',
  styleUrls: ['./avatar.component.scss'],
  styles: [`
    :host {
      display: inline-block;
    }
  `
  ]
})
export class AvatarComponent {

  @Input() label: string;
}

Desired result:

Component specification:

Answer

git checkout 2a-answer
<div class="h-6 w-6 rounded-full bg-red-500 text-white flex items-center justify-center">
  {{label}}
</div>

2b. Use the tailwind @apply to move your html classes into your scss file.

git checkout 2b-start
Answer

git checkout 2b-answer
avatar.component.html

<div class="avatar">
  {{label}}
</div>

avatar.component.scss

.avatar {
  @apply h-6 w-6 rounded-full bg-red-500 text-white flex items-center justify-center;
}

2c. Create an svg-button component

Desired result:

git checkout 2c-start

In this branch an app-svg component has already been created for you.

ng g c svg-button

Component specification:

  • 1.5rem height
  • 1.5rem width
  • the background is gray-200
  • when hovered, the background should transition to gray-300 over 200ms
  • the cursor should be a pointer
  • the X should be vertically and horizontally centered
  • a circle
Answer

git checkout 2c-answer
svg-button.component.html

<div class="svg-button-wrapper">
  <app-svg [name]="name"></app-svg>
</div>


svg-button.component.scss

:host {
  @apply inline-flex;
}

.svg-button-wrapper {
  @apply inline-flex items-center justify-center h-6 w-6 bg-gray-200 rounded-full cursor-pointer hover:bg-gray-300;
  transition: background-color 200ms ease-in-out;
}

2d. Create the chip component

Desired result:

git checkout 2d-start

A chip component was already created in the 2d-start branch. Fill it out to create the component.

Component specification:

  • The component should be composed of the avatar, label text, a close button
  • the component should be rounded
  • the background should be gray-200
  • the text should be small (.875 rem)
  • there should be .5rem of horizontal padding around label
  • the label text (and all composed parts) should be vertically center
Answer

git checkout 2d-answer
chip.component.html

<div class="chip-wrapper">
  <app-avatar [label]="firstLetters"></app-avatar>
  <div class="chip-label">{{label}}</div>
  <app-svg-button name="times" (click)="onClose()"></app-svg-button>
</div>

chip.component.scss

.chip-wrapper {
  @apply inline-flex rounded-full items-center bg-gray-200;
}

.chip-label {
  @apply text-gray-700 text-sm px-2;
}

Exercise 3 - creating reusable input styles

3a. Create basic input styling

**Do your works in the styles.scss

Desired result:

git checkout 3a-start

Component specification:

  • text should be .875rem and gray-900
  • border should be gray-300 and rounded
  • there should be .5rem of vertical padding
  • there should be .75rem of horizontal padding
  • the final product should be 35 px in height
  • the default 'outline' should be removed (when you focus the input)

** If your input has more height than expected it could be the line height. Line height is the amount of vertical space that text takes up. For example, if you have a multiline paragraph, the line-height will dictate how much space is between each line. Having good spacing between lines of text affects readability and can make or break how your paragraphs look. Tailwind has a default line height of 1.5rem which is not desired in this situation. Can you figure out how to control this using tailwind utility classes?

Answer

git checkout 3a-answer
styles.scss

.input {
  @apply px-3 py-2 text-sm text-gray-900 border border-gray-300 rounded outline-none leading-none;
  ...existing styles...
}

3b. create focus styling

Desired result:

git checkout 3b-start

Component specification (when focused):

  • the border should transition to blue-300 over 200ms
  • an additional 3px semi-transparent blue 'border' should be added to make the input glow

** Did you know outset box shadow is rendered outside the element? Box shadow doesn't take up any space, but rather cuts into the existing space which ensures that the height of your element doesn't change, which would cause elements on your page to move.

Hint

box-shadow: 0px 0px 0px 3px rgba(66, 153, 225, 0.35);

Answer

git checkout 3b-answer
styles.scss

.input {
  ...existing styles...
  transition: all 200ms ease-in-out;
}

.shadow-focus {
  box-shadow: 0px 0px 0px 3px rgba(66, 153, 225, 0.35);
}

.input:focus {
  @apply shadow-focus border-blue-300;
}

3c. create disabled styling

Component specification (when disabled):

  • the background should be gray-100
  • the text should be gray-500
Answer

git checkout 3b-answer
styles.scss

.input[disabled] {
  @apply bg-gray-100 text-gray-500;
}

3d. create error styling

Component specification (when error attribute exists):

  • the border should transition be red-300
  • an additional 3px semi-transparent red 'border' should be added to make the input glow

** note remember from the last example how to use css attribute selectors

Hint

box-shadow: 0px 0px 0px 3px rgba(245, 101, 101, 0.35);

Answer

git checkout 3d-answer
styles.scss

.shadow-error {
  box-shadow: 0px 0px 0px 3px rgba(245, 101, 101, 0.35);
}

.input[error] {
  @apply shadow-error border-red-300;
}

Exercise 4 - build the drawing

In exercise 2 we built reusable angular components. In this exercise the goal is to produce an image using html and css, not make a component functional or for reuse. So go ahead and hardcode text, paste an svg right into the html, or set a style on an html element. You'll to use tailwind classes directly in the html rather than externalizing them into an scss file. If you're spending time thinking about what html tag to use make it a div. The answers use div tags exclusively.

4a. Create an alert component

ng g c alert

** requirement: the max-width of the alert should be 20rem

style="max-width: 20rem"

Answer

git checkout 4a-answer
<div class="p-4 rounded bg-white border-t-4 border-blue-900 shadow-xl inline-block" style="max-width: 20rem">
  <div class="flex items-center">
    <div class="rounded-full h-10 w-10 bg-blue-900 flex-shrink-0 flex items-center justify-center">
      <div class="text-white h-4 w-4 mb-1">
        <svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="bell"
             class="svg-inline--fa fa-bell fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
          <path fill="currentColor"
                d="M439.39 362.29c-19.32-20.76-55.47-51.99-55.47-154.29 0-77.7-54.48-139.9-127.94-155.16V32c0-17.67-14.32-32-31.98-32s-31.98 14.33-31.98 32v20.84C118.56 68.1 64.08 130.3 64.08 208c0 102.3-36.15 133.53-55.47 154.29-6 6.45-8.66 14.16-8.61 21.71.11 16.4 12.98 32 32.1 32h383.8c19.12 0 32-15.6 32.1-32 .05-7.55-2.61-15.27-8.61-21.71zM67.53 368c21.22-27.97 44.42-74.33 44.53-159.42 0-.2-.06-.38-.06-.58 0-61.86 50.14-112 112-112s112 50.14 112 112c0 .2-.06.38-.06.58.11 85.1 23.31 131.46 44.53 159.42H67.53zM224 512c35.32 0 63.97-28.65 63.97-64H160.03c0 35.35 28.65 64 63.97 64z"></path>
        </svg>
      </div>
    </div>
    <div class="ml-4">
      <div class="text-gray-900 font-semibold text-sm">
        Important information
      </div>
      <div class="text-gray-500 text-xs mt-1">
        Make sure you read this information before you continue.
      </div>
    </div>
  </div>
</div>

4b. Create a home screen

ng g c home-screen

** guidance:

Answer

git checkout 4b-answer
<div class="rounded-2xl bg-blue-900 p-6 w-96 overflow-hidden">
  <div class="relative w-full">
    <div class="bg-blue-500 rounded-full h-60 w-60 absolute top-0 right-0 opacity-50"
         style="margin-top: -4rem; margin-right: -4rem">
    </div>
    <div class="bg-blue-500 rounded-full h-10 w-10 absolute top-0 left-0 opacity-50"
         style="margin-top: 9rem; margin-left: 7rem">
    </div>
  </div>
  <div
    class="text-xs font-medium leading-none rounded-full inline-flex items-center px-2 py-1 bg-gray-200 text-gray-800">
    BETA
  </div>
  <div class="mt-36 text-blue-300 text-xs">
    HOME
  </div>
  <div class="text-4xl font-medium text-gray-200">
    Goodmorning,
  </div>
  <div class="text-4xl font-medium text-gray-200">
    Jim
  </div>
  <div class="bg-blue-500 opacity-50 text-gray-200 text-xs rounded-full w-full px-3 py-3 leading-none mt-4 mb-12">
    Search
  </div>
</div>

<div class="rounded-2xl w-96 p-4 bg-white text-gray-900 shadow-lg z-10" style="margin-top: -2rem;">

  <div class="flex items-center mb-4">
    Messages
    <div class="ml-2 px-2 rounded-full text-xs bg-blue-200 text-blue-900 font-medium">
      5
    </div>
  </div>

  <div class="bg-gray-100 rounded-lg px-2 py-3">
    <div class="flex items-center">
      <div class="p-2 bg-blue-500 rounded-lg w-12 h-12 flex-shrink-0">
      </div>
      <div class="w-full flex justify-between">
        <div class="px-3">
          <div class="text-sm">Jim Bean</div>
          <div class="text-xs text-gray-500">this is a message</div>
        </div>
        <div class="text-xs">8:44 am</div>
      </div>
    </div>
  </div>

  <div class="px-2 py-3">
    <div class="flex items-center">
      <div class="p-2 bg-blue-200 rounded-lg w-12 h-12 flex-shrink-0">
      </div>
      <div class="w-full flex justify-between">
        <div class="px-3">
          <div class="text-sm">Jane Bean</div>
          <div class="text-xs text-gray-500">this is another message message</div>
        </div>
        <div class="text-xs">2 days ago</div>
      </div>
    </div>
  </div>

  <div class="px-2 py-3">
    <div class="flex items-center">
      <div class="p-2 bg-blue-800 rounded-lg w-12 h-12 flex-shrink-0">
      </div>
      <div class="w-full flex justify-between">
        <div class="px-3">
          <div class="text-sm">Joe Pinto</div>
          <div class="text-xs text-gray-500">this is another message message</div>
        </div>
        <div class="text-xs">2 days ago</div>
      </div>
    </div>
  </div>
</div>

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published