Alloy startpage with Tailwind CSS lab

I've really taken a liking to Tailwind CSS and to help spread the word I did a quick lab of using it on the Alloy startpage.

Note 2022: A lot has happend with Tailwind CSS and most of this post is highly dated.

Tailwind CSS is not your typical CSS framework. Basically it just provides utility classes that work on any semantic structure so that you can do most work without leaving your HTML. It's very smartly composed so even if you're competent in CSS it doesn't hinder you, instead you probably work faster with Tailwind than you would writing our own CSS.

Outside of the official web site these are some useful links:

In my quick lab I reference Tailwind CSS straight off the CDN so everything is the default configuration. For production you would have your own configuration and in my cases I've used a Webpack project that generate bundled files. I'll post a config and boilerplate project with a sensible Epi styling to use for Edit/Admin Mode plugins shortly. But here I just replace @Styles.Render("~/bundles/css") with a CDN reference.

<link href="https://unpkg.com/tailwindcss@("@")^1.0/dist/tailwind.min.css" rel="stylesheet" />

Then change the first wrapping DIV in the Root layout file.

<div class="container mx-auto py-4 px-2">

Quoting Tailwind's documentation on the container class:

The .container class sets the max-width of an element to match the min-width of the current breakpoint. This is useful if you'd prefer to design for a fixed set of screen sizes instead of trying to accommodate a fully fluid viewport.

I make some small adjustments to the TeaserBlock views, just adding some padding and typography classes, similar to these modifications in the Jumbotron view.

<div class="px-2 py-6 clearfix">
    <div class="max-w-sm md:float-left">
        @Html.PropertyFor(m => m.Image)
    </div>
    <h1 class="mb-2 leading-tight text-5xl text-gray-800" @Html.EditAttributes(m => m.Heading)>@Model.Heading</h1>
    <p class="mb-6 text-xl text-gray-800" @Html.EditAttributes(m => m.SubHeading)>@Model.SubHeading</p>
    <a class="float-right bg-gray-800 text-white font-bold py-2 px-4 border rounded" href="@Model.ButtonLink" id="jumboLink" @Html.EditAttributes(m => m.ButtonText)>@Model.ButtonText</a>
</div>

In Views\StartPage\Index.cshtml I need to get some classes on the ContentArea wrapping div.

@Html.PropertyFor(x => x.CurrentPage.MainContentArea, new { CssClass = "flex flex-wrap", tag = Global.ContentAreaTags.FullWidth })

Then of course also change to Tailwind names in the AlloyContentAreaRenderer class and try to mimic the old Bootstrap behaviour.

private static string GetCssClassForTag(string tagName)
{
  const string DefaultBlockClasses = "w-full sm:w-6/12 xl:w-4/12";

  if (string.IsNullOrEmpty(tagName))
  {
    return DefaultBlockClasses;
  }

  switch (tagName.ToLower())
  {
    case "span12":
      return "w-full";
    case "span8":
      return "w-full xl:w-8/12";
    case "span6":
      return "w-full md:w-6/12";
    default:
      return DefaultBlockClasses;
  }
}

A note on the breakpoints (md, xl etc) is to aim for a config with as few screen breakpoints as possible. Every breakpoint will add to the file size. I got away with just one that I named pc in my biggest project thus far.

screens: {
  'pc': '700px'
}

Finally I put some classnames in the footer with the following structure.

<hr class="my-8" />
<div class="flex flex-wrap px-8 lg:justify-center">
  <div class="mb-6 w-40">
    <h3 class="text-lg text-gray-800">@Html.Translate("/footer/products")</h3>

Running the site now we got the modified startpage in order. I added some copied blocks and set the Display Option for last the one to take up more width space.

View screen recording (animated GIF, 6.32 MB)

The responsive behaviour of Alloy is a bit dated but as you can see it was really fast and simple to mimic it using Tailwind CSS. Hopefully you've gotten a feel for how it works and an interest to learn more. I especially recommend watching the screencasts.

When you move further and got TinyMCE generated markup in an element modifying every element with classes might be a bit out of reach so something like shown in this issue comment on article text approach on Github from Adam Wathan is what you need to tweak (pasted below just in case) and scope around the TinyMCE content. Of course you'll use this class in the Episerver CMS Edit Mode setup of TinyMCE as well.

.markdown {
  @apply text-lg text-grey-darkest leading-normal;
  & > * + *,  & li + li, & li > p + p {
    @apply mt-6;
  }
  & strong {
    @apply text-black font-bold;
  }
  & a {
    @apply text-black font-semibold;
  }
  & strong a {
    @apply font-bold;
  }
  & h2 {
    @apply leading-tight text-xl font-bold text-black mb-2 mt-10;
  }
  & h3 {
    @apply leading-tight text-lg font-bold text-black mt-8 -mb-2;
  }
  & code {
    @apply font-mono text-sm inline bg-grey-lighter px-1;
  }
  & pre code {
    @apply block bg-black p-4 rounded;
  }
  & blockquote {
    @apply border-l-4 border-grey-light pl-4 italic;
  }
  & ul, & ol {
    @apply pl-5;
    @screen sm {
      @apply pl-10;
    }
  }
}

Published and tagged with these categories: Episerver, Development