<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>@mdo</title>
 <link href="https://markdotto.com/atom.xml" rel="self"/>
 <link href="https://markdotto.com/"/>
 <updated>2024-06-11T21:29:13+00:00</updated>
 <id>https://markdotto.com/</id>
 <author>
   <name>Mark Otto</name>
   <email>markdotto@gmail.com</email>
 </author>

 
 <entry>
   <title>Working with MDX in Next.js</title>
   <link href="https://markdotto.com/2024/06/03/nextjs-mdx/"/>
   <updated>2024-06-03T00:00:00+00:00</updated>
   <id>https://markdotto.com/2024/06/03/nextjs-mdx</id>
   <content type="html">&lt;p&gt;Several weeks ago, I completely redesigned, rewrote, and re-engineered the &lt;a href=&quot;https://pierre.co/docs&quot;&gt;Pierre Docs&lt;/a&gt;. What originally started as a few Notion pages had already turned into a set of low-key static pages on our logged out site, but after a slew of awesome product updates, our very manual setup was severely lacking and we simply needed more docs.&lt;/p&gt;

&lt;div&gt;
	&lt;a class=&quot;fw-img-link&quot; href=&quot;https://pierre.co/docs&quot; target=&quot;_blank&quot;&gt;
		&lt;img src=&quot;/uploads/2024/05/pierre-docs-home.png&quot; alt=&quot;Pierre Docs home&quot; /&gt;
	&lt;/a&gt;
&lt;/div&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;The homepage for the new Pierre Documentation.&lt;/p&gt;

&lt;p&gt;I needed an easy way to write and maintain dozens of new pages of documentation. I had just recently redone the &lt;a href=&quot;https://pierre.co/changelog&quot;&gt;Pierre Changelog&lt;/a&gt; from a similar manual setup to use MDX and dynamic routes in Next.js, and I wanted to do the same for our docs, too.&lt;/p&gt;

&lt;h2 id=&quot;learning-new-things&quot;&gt;Learning new things&lt;/h2&gt;

&lt;p&gt;There’s a ton about Next.js and React that I didn’t fully know heading into this, so it took me a bit to get up to speed on a few concepts. I’m reiterating them here for my own memory and reference, but at the same time, I want to help others who might be in a similar spot. There’s no shortage of advice and posts out there, but none felt like they explained things in a helpful way for me.&lt;/p&gt;

&lt;p&gt;Okay, so here’s a few things I needed to learn or remind myself heading into this project.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Files or folders with brackets in their names like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[slug]&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[slug].js&lt;/code&gt; are &lt;a href=&quot;https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes&quot;&gt;dynamic route segments&lt;/a&gt;. These allow you to group files and folders of related content while generating routes for your content. In short, you can render any number of MDX pages using this page as a template.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There’s also a special catch-all version of dynamic routes that works across nested folders by prefacing your dynamic segment with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;...&lt;/code&gt;. In my case with the Pierre docs, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/src/docs/[...slug]/page.tsx&lt;/code&gt; is the dynamic segment that allows us to render any docs MDX page, no matter the subfolder.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://nextjs.org/docs/app/api-reference/functions/generate-static-params&quot;&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateStaticParams&lt;/code&gt; function&lt;/a&gt; works with dynamic routes to generate each static page. This function is used within those dynamic segments, and when it’s told where to look for say a bunch of MDX files in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/src/docs/content/&lt;/code&gt; directory, it will loop over those to statically generate each page. Neat!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now there’s also some stuff I already knew that bears repeating:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://mdxjs.com/&quot;&gt;MDX&lt;/a&gt; is a format that lets you write JSX in your Markdown documents. You can create and extend React components that can be used alongside Markdown content. Super nice for our alerts, buttons, and icons.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Grouping and ordering MDX files still seems like a pain in the ass, and what I mean by that is specifically around generating our docs side navigation. Our best approach here was generate the folders of static pages and use a separate JSON object to order and generate the nav.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;There are &lt;em&gt;so&lt;/em&gt; many ways to manage MDX, and most of them require the use of plugins to get all the functionality you really want. No issue here, but it’s worth noting that I ended up using &lt;a href=&quot;https://github.com/hashicorp/next-mdx-remote&quot;&gt;next-mdx-remote&lt;/a&gt;, some Rehype plugins, and some Remark plugins. All told, it’s been great for me.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay with that stuff out of the way, let’s get to the good stuff—how I built the Pierre Docs using MDX and Next.js.&lt;/p&gt;

&lt;h2 id=&quot;implementation-goals&quot;&gt;Implementation goals&lt;/h2&gt;

&lt;p&gt;Right before doing the Pierre docs, I had just &lt;a href=&quot;https://pierre.co/changelog&quot;&gt;redone the Pierre Changelog&lt;/a&gt;. The first iteration of it was a single page where individual entries were separate component imports and you’d link to entries with a URL hash.&lt;/p&gt;

&lt;p&gt;It looked like this:&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;styles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GithubMirror&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BranchSummaries&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;MultiplayerEditor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Mentions&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BlendedDiffs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
  ...
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It worked for a bit, but it obviously wouldn’t go anywhere as we grow and ship more. It was already annoying after a handful of posts. What I worked up for the second iteration of the Changelog though was built for a single, flat directory. That wouldn’t suffice here.&lt;/p&gt;

&lt;p&gt;Plus, I had some specific goals in mind for what I’d need to build.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Must support dozens of pages&lt;/li&gt;
  &lt;li&gt;Must support any number of nested directories&lt;/li&gt;
  &lt;li&gt;Must be easy to contribute to by anyone on the team&lt;/li&gt;
  &lt;li&gt;Eventually, must be abstracted to easily scale to other content directories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Okay, so with that in mind, I set out to get some help and start building.&lt;/p&gt;

&lt;h2 id=&quot;setting-up-the-file-structure&quot;&gt;Setting up the file structure&lt;/h2&gt;

&lt;p&gt;Our Next.js app has (what seems to me like) a fairly straightforward setup. For content that doesn’t require signing in, we use some middleware to render our logged out and marketing pages. The rough structure looks a bit like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pierre/
├── src/
│   ├── app/
│   │   ├── (authenticated)/
│   │   ├── changelog/
│   │   ├── docs/
│   │   ├── og/
│   │   ├── signin/
│   │   └── ...
│   ├── components/
│   ├── lib/
│   ├── primitives/
│   └── ...
├── next.config.mjs
├── package-lock.json
├── package.json
└── ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looking inside the docs folder, here’s what we’re working with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docs/
├── [...slug]/
│   └── page.tsx
├── components/
├── content/
├── layout.tsx
├── page.module.css
└── page.tsx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The local (to the docs source) content folder is where we put all our MDX files. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page.tsx&lt;/code&gt; file is the main component that renders the MDX content, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[...slug]&lt;/code&gt; folder is where we generate all our static pages using those fancy dynamic routes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You could put your content elsewhere, but in the interest of limiting scope and ensuring easy access, I kept it simple and put it all in Git as local MDX files. Eventually I could see us looking into some external CMS.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;rendering-mdx&quot;&gt;Rendering MDX&lt;/h2&gt;

&lt;p&gt;Now that we have our files in place, we can start figuring out how to render the MDX into static HTML. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[...slug]/page.tsx&lt;/code&gt; file is where we fetch and render the local MDX content. We use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateStaticParams&lt;/code&gt; function within to generate our static pages with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next-mdx-remote&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// app/src/docs/[...slug]/page.tsx&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;node:fs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;node:path&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;runtime&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;nodejs&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dynamic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;force-static&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;contentSource&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;src/app/docs/content&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;generateStaticParams&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Recursively fetech all files in the content directory&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readdirSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;contentSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;recursive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Declare an empty array to store the files&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// If the target is a directory, skip it, otherwise add it to the files array&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lstatSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
					&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;contentSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Built the files array&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// Return the files array with the slug (filename without extension)&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.mdx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Some more things to note here that I learned along the way:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;There are apparently two ways to work with this kind of stuff in Next.js—called &lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/rendering/edge-and-nodejs-runtimes&quot;&gt;runtimes&lt;/a&gt;—and that’s using Node or using &lt;em&gt;the edge&lt;/em&gt;. Node is what we want since we’re statically rendering this content. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;runtime&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node&lt;/code&gt; related imports are all in support of that. &lt;strong&gt;Update:&lt;/strong&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nodejs&lt;/code&gt; is the default, so we don’t need to declare this here. Leaving it in for posterity.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Since we want these rendered HTML pages to be static, we can &lt;a href=&quot;https://nextjs.org/docs/app/api-reference/file-conventions/route-segment-config#dynamic&quot;&gt;force that behavior in the Next.js app directory&lt;/a&gt; by setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dynamic&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;force-static&lt;/code&gt;. Since we’re using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateStaticParams&lt;/code&gt;, this is also optional, but it’s always good to be explicit.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Getting that list of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;targets&lt;/code&gt; in the source directory will include sub-directories alongside files, so we need to filter those out. That’s what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;isDirectory&lt;/code&gt; check handles.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The final piece of that function is to push all the files into an array and return them with the slug. We’ll use this later to help generate the pages by their slug.&lt;/p&gt;

&lt;p&gt;Okay, now onto rendering the page! To do that, we need to build a default function for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;page.tsx&lt;/code&gt; file that takes the information from the magical &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generateStaticParams&lt;/code&gt; function and renders the MDX content.&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Continuing in app/src/docs/[...slug]/page.tsx&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Add new imports&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;useMDXComponents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@/mdx-components&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compileMDX&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;next-mdx-remote/rsc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rehypeHighlight&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rehype-highlight&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rehypeSlug&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;rehype-slug&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;remarkGfm&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;remark-gfm&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;


&lt;span class=&quot;kr&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Params&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nl&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DocsPage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Read the MDX file from the content source direectory&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readFileSync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cwd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;contentSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;slug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.mdx&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// MDX accepts a list of React components&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;useMDXComponents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({});&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// We compile the MDX content with the frontmatter, components, and plugins&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;frontmatter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;compileMDX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
			&lt;span class=&quot;na&quot;&gt;mdxOptions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;rehypePlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rehypeHighlight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;rehypeSlug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;remarkPlugins&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remarkGfm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;na&quot;&gt;parseFrontmatter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// (Optional) Set some easy variables to assign types, because TypeScript&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pageTitle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;frontmatter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pageDescription&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;frontmatter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

	&lt;span class=&quot;c1&quot;&gt;// Render the page&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;styles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pageTitle&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pageTitle&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pageDescription&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mdStyles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;renderedMarkdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;styles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;docsBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
				&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Okay so let’s walk through a few things…&lt;/p&gt;

&lt;p&gt;We’re importing a few new things—the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;useMDXComponents&lt;/code&gt; function and a few plugins for our MDX content. We’re also importing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compileMDX&lt;/code&gt; function from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next-mdx-remote/rsc&lt;/code&gt; to render the MDX content.&lt;/p&gt;

&lt;p&gt;Here’s a simplified version of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src/mdx-components.ts&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-ts highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/mdx-components.ts&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MDXComponents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;mdx/types&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ImageProps&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;next/image&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// other imports...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;useMDXComponents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MDXComponents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MDXComponents&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;className&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;styledLink&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;children&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/a&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;		&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;hr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;React&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ComponentProps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Divider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Divider&lt;/span&gt;
				&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;{...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;		&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Image&lt;/span&gt;
				&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;{...(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;props&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;ImageProps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
			&lt;span class=&quot;sr&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;
&lt;/span&gt;		&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;components&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you’re new to &lt;a href=&quot;https://mdxjs.com/docs/using-mdx/#components&quot;&gt;using MDX components&lt;/a&gt;, this basically let’s you override default HTML elements rendered by MDX and make your own components available to use in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mdx&lt;/code&gt; files. For example, in the above snippet we change all default anchor elements to have the class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;styledLink&lt;/code&gt;. We also override the default horizontal rule to use our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Divider&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Back to the rest of the page…&lt;/p&gt;

&lt;p&gt;Our components and the MDX plugins that we want are passed to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compileMDX&lt;/code&gt; function to render the content. Those are straightforward, so I won’t get into them. We also parse the frontmatter from the MDX file to get the page title and description. We also use fetch a few other things from our page frontmatter—icon, color, OG image, etc—but we won’t get into that here. Lastly, we put it all together at the end in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;return&lt;/code&gt; to build the page’s HTML.&lt;/p&gt;

&lt;p&gt;For the Markdown styling, we have a stylesheet that we made for our file explorer when &lt;a href=&quot;https://pierre.co/changelog/file-explorer-render/&quot;&gt;we added rendered Markdown support&lt;/a&gt;. That’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mdStyles.renderedMarkdown&lt;/code&gt; part. There wasn’t much to tweak here either since everything else fell into customizing MDX components.&lt;/p&gt;

&lt;p&gt;From here, we have MDX pages that can be dynamically rendered at any level of the source directory, with easy frontmatter access and custom components, plus a set of functions that can be easily extended into other areas of the site.&lt;/p&gt;

&lt;h2 id=&quot;sidenav&quot;&gt;Sidenav&lt;/h2&gt;

&lt;p&gt;One bummer about directories of Markdown/MDX has always been building navigation for those pages—seemingly no matter the framework or language. Setting the order, adding icons, controlling states—woof. We could use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fs&lt;/code&gt; to read from the directory and build a nav ourselves, but how would we order a dynamic set of pages within each sub-directory? Frontmatter could maybe help, but then you’re stuck updating values across multiple pages.&lt;/p&gt;

&lt;p&gt;The easiest solution is still building a single config file of sorts for the navigation using JSON or YML. We took that route with the docs pages—here’s a snippet of it.&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/app/docs/Nav.tsx&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DocsNav&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Getting Started&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;IconBook&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;purple&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/getting-started&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Overview&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/getting-started/new&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Create a New Workspace&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/getting-started/join&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Join an Existing Workspace&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/getting-started/import-code&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Import Code&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/getting-started/ssh&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Setup SSH&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Workspaces&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;IconBuilding&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
		&lt;span class=&quot;na&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Overview&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/navigation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Navigation&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/members&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Members&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/repositories&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Repositories&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/notifications&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Notifications&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/presence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Presence&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/docs/workspaces/settings&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Settings&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Elsewhere, we use that JSON to build our sidebar as its own component that can then be rendered wherever we want in our docs layout. Here’s a look at how we built that with our own components:&lt;/p&gt;

&lt;div class=&quot;language-jsx highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Colors&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@/primitives/Color&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Column&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@/primitives/Layout&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Icons&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;@/primitives/icons&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;react&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DocsNav&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./Nav&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NavHeader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./NavHeader&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;NavItem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;./NavItem&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;DocsMenu&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;DocsNav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NavHeader&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;header&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Colors&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;icon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Icons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;icon&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;keyof&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Icons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;na&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Column&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;gap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt;
					&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;menuItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
						&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NavItem&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
							&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
						&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NavItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
					&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;
				&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
			&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;NavHeader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
		&lt;span class=&quot;p&quot;&gt;))}&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We used the same approach overall with our docs homepage, except we created a separate JSON blurb and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; since we only wanted to show a subset of pages that we hand-selected. This gave us a bit more flexibility, but it’s also something we could maybe improve down the line as well to avoid the repetition.&lt;/p&gt;

&lt;h2 id=&quot;up-next-abstraction&quot;&gt;Up Next: Abstraction&lt;/h2&gt;

&lt;p&gt;The last goal for me was to be able to abstract all of this so I can use it elsewhere—like on the Changelog or in the Styleguide I’ve been (very) slowly chipping away at. I’ll save that for another post as I’m still working on that part.&lt;/p&gt;

&lt;p&gt;Suffice to say it has also felt relatively straightforward to do and I love that I’m able to get this stuff working elsewhere with ease now.&lt;/p&gt;

&lt;p&gt;See you again for the next part!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Shipping Blended Diffs</title>
   <link href="https://markdotto.com/2024/01/17/blended-diffs/"/>
   <updated>2024-01-17T00:00:00+00:00</updated>
   <id>https://markdotto.com/2024/01/17/blended-diffs</id>
   <content type="html">&lt;p&gt;It’s been a whopping five years since I last shipped &lt;a href=&quot;/2018/02/07/github-system-fonts/&quot;&gt;one of my Shipping blog posts&lt;/a&gt;, and boy do I have a good one to come back with. I’ve been working on Pierre for most of the last year and we’ve been &lt;a href=&quot;https://pierre.co/changelog&quot;&gt;shipping some amazing stuff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s talk about the latest, designing and shipping blended diffs in &lt;a href=&quot;https://pierre.co&quot;&gt;Pierre&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-final.png&quot; alt=&quot;Blended diffs&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;The final version of blended diffs in Pierre, complete with collapsed deletions, new modifications, and overall lighter design.&lt;/p&gt;

&lt;p&gt;Since starting Pierre, we’ve been focused on finding ways to rethink the tools and features we’ve relied on for decades as developers. A few months ago, I decided to do a deep dive into how we can render code changes differently. Just a fun and open-ended exploration in Figma of any and all ideas that came to mind. Most of my Figma files end up looking something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-diff-explorations.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;One of six Figma pages. I always make it a goal to generate as many artboards/frames as possible. It’s fun to see the turning point towards blended diffs in the middle of the page.&lt;/p&gt;

&lt;p&gt;And since designing diffs and code changes is an area I’ve thought a fair amount about since first &lt;a href=&quot;/2014/09/04/shipping-githubs-split-diffs/&quot;&gt;shipping split diffs at GitHub&lt;/a&gt; back in 2014, I was very excited to dive in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-diffs-new-features.png&quot; alt=&quot;Early explorations&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;An early mockup of a file tree table of contents, inline actions on hover, diff options, and more. None of this shipped, but maybe in a future update.&lt;/p&gt;

&lt;p&gt;Most of my early explorations like the one above started by &lt;em&gt;adding&lt;/em&gt; features to our diffs and reviews, which quickly started to feel like the wrong approach. Instead of adding a bunch of new or improved stuff—which, honestly, we still want to do at some point—what would happen if we started by trying to remove bits and pieces? That’s ultimately what led me to something I started calling &lt;em&gt;blended diffs&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;finding-a-new-style&quot;&gt;Finding a new style&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Blended diffs are an all new diff style&lt;/strong&gt; that emphasizes a file’s finished state, minimizes deletions, simplifies one-line modifications, and creates more space for context. All in an effort to decrease review time and make code changes more approachable.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-v1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;The first iteration that added a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; indicator and blue “modified” line treatment.&lt;/p&gt;

&lt;p&gt;This was the first iteration of a new “modified line” treatment where I treated the 1-line diff as just that, one line with an inline change. Until this point, single line changes show up as two lines of a diff, like this:&lt;/p&gt;

&lt;div class=&quot;language-diff highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;gd&quot;&gt;- This is the deleted line
&lt;/span&gt;&lt;span class=&quot;gi&quot;&gt;+ This is the new line
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And this started to really bother me because I spent more time looking at the two lines rather than the one-word inline change. Newer diff tools of course have added inline highlighting to help with this, but it was still the same thing at heart. So I kept pushing.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-v2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;The first attempt at a blended diff with modifications and a faded deletion.&lt;/p&gt;

&lt;p&gt;The very next iteration dropped the notion of a split or stacked diff, instead &lt;em&gt;blending&lt;/em&gt; the changes inline with the rest of the file. &lt;em&gt;See what I did there?&lt;/em&gt; I was still stuck on all blue here, which I quickly realized wasn’t ideal as it’s unclear if the change was a deletion or an addition. Several iterations later, I landed on a balance of those blue modified indicators and green or red inline treatments.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-context.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;All one-line modifications have blue line numbers and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~&lt;/code&gt; indicators. One-line additions have a green background, while one-line deletions are indicated with a red vertical bar.&lt;/p&gt;

&lt;p&gt;Clicking on the red bar for deletions would toggle a popover to show a regular diff.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-context-popover.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This iteration also included the first ideas for inline summaries of deletions and hidden lines. The dream was to show the number of lines and a semantic summary of what was behind that hidden deletion. For example, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2 constants, 1 line break&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 unused Button function&lt;/code&gt;. Originally this was going to be something I planned to push for down the line, but once we got into code, we switched gears on that once we got to building it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-gutter.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;One of the last elements of the new blended diffs was a column left of the line numbers. I really liked the idea of a left-hand column called “the gutter”. The blended diff gutter is a consistent space for context on any line—annotation markers, avatars for comments, and eventually even more. I see this scaling to more custom annotations, like todos or linters, and whatever else we can dream up.&lt;/p&gt;

&lt;h2 id=&quot;planning-with-the-team&quot;&gt;Planning with the team&lt;/h2&gt;

&lt;p&gt;As the design iterations started feeling better and better, it felt time to get out of Figma and write down my thoughts to better articulate product direction and get some early feedback. Writing about a feature is arguably more powerful and meaningful than just designing it.&lt;/p&gt;

&lt;p&gt;Our team likes to spike out our ideas and then gather our thoughts before we fully (or over) commit to something. We built that right into Pierre with branches—you can start writing and getting a review before pushing any code.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-prd.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;Product doc for blended diffs with Figma embed, motivation, goals, and more.&lt;/p&gt;

&lt;p&gt;The biggest question sparked by the PRD was how to launch this new diff style—alongside stacked and split, in place of one, or in place of both? Adding a third diff style would be the safest. Replacing one of them would be a little risky. Replacing both would be making a bigger bet. So after some back and forth, we went big.&lt;/p&gt;

&lt;p&gt;Blended diffs would replace both existing diff styles—making for less code to maintain, less bloat, and a more opinionated product.&lt;/p&gt;

&lt;h2 id=&quot;building-it&quot;&gt;Building it&lt;/h2&gt;

&lt;p&gt;After getting a clear direction set in stone between design and PRD, we started building. We went back and forth between more rounds in Figma and writing code, a process I really love when working with a product engineer. There’s no better way to fine-tune the details than to ping-pong between design and code, and designer and engineer.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-blended-diffs-context-left.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ian led the charge on building out blended diffs while I provided some frontend support. It ended up being super helpful to be dropping the old diff styles because it was &lt;em&gt;significantly&lt;/em&gt; less code to be working around. Our stacked and split diffs naturally shared some code, so adding a third was going to be messy. Making that early bet let us move much faster.&lt;/p&gt;

&lt;p&gt;Design-wise, we started with the inline deletion summaries on the left and intersecting the line numbers. This felt too busy once we tried using it, and leading with the number of lines instead of the summary felt like we were burying the lead. We ended up moving the summaries to the right (on desktop) and leading with our AI generated summaries. This has the effect of you noticing a subtle indicator that there’s a deletion, and then you can choose to dig in or not without it taking away too much attention.&lt;/p&gt;

&lt;p&gt;Jacob hooked it up so that deleted lines are fed into an AI model to summarize the deletions for us on the fly (and then cached). We experimented with summarizing more parts of the diff, including every line of every file, but that ended up being less accurate and obviously slower and more expensive. We also took some time to fine-tune the spacing and style, ensuring those hidden deletions didn’t interrupt the flow of the lines of code too much.&lt;/p&gt;

&lt;video src=&quot;/uploads/2024/01/pierre-blended-diffs-expand.mp4&quot; controls=&quot;true&quot;&gt;&lt;/video&gt;

&lt;p&gt;While we were in there working on the new diff styles, we also took some time out to further minimize deleted files. Now the stuff you don’t need to see as much—like a list of deleted images—can be collapsed to save space, reduce review time, and further improve comprehension.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2024/01/pierre-diff-deletions.png&quot; alt=&quot;Deletions&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The same treatment also now applies to very large diffs, like package lockfiles. All minimized and tucked away until you really need to dig in. We really focused in on the idea of &lt;em&gt;comprehension&lt;/em&gt; with blended diffs. If we could help people understand what happened faster, and remove the noise, we could make code reviews faster and more enjoyable independent of any other workflow improvements.&lt;/p&gt;

&lt;p&gt;Building like this took longer than expected given the holidays, but the extra bake time really helped us hone details around style, interaction, and performance as we continued to use it internally. It also helped a ton that we have super easy and Pierre-native comments for our Vercel branch deploys—the engineers could just screenshot a visual bug for me and it’d show up for me in the branch to fix.&lt;/p&gt;

&lt;p&gt;I can’t say it enough times—product designers and product engineers pairing from design to code is absolutely essential to &lt;em&gt;great&lt;/em&gt; products. I’m super proud and thankful to be working with this team and building something like Pierre.&lt;/p&gt;

&lt;h2 id=&quot;a-diff-canvas&quot;&gt;A diff canvas&lt;/h2&gt;

&lt;p&gt;There are like a dozen more ideas we landed on while working on blended diffs, but I don’t want to tip our hat too much before we’re ready. We’re &lt;em&gt;very&lt;/em&gt; committed to changing how product engineers work, and diffs are just one piece of that. We truly believe these new diffs are a blank canvas for us to keep building on.&lt;/p&gt;

&lt;p&gt;Keep an eye on the &lt;a href=&quot;https://pierre.co/changelog&quot;&gt;Pierre Changelog&lt;/a&gt; and &lt;a href=&quot;https://discord.gg/QJtTu5hpzx&quot;&gt;join our community Discord&lt;/a&gt; to get access to our private alpha.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>macOS web apps</title>
   <link href="https://markdotto.com/2023/10/01/macos-web-apps/"/>
   <updated>2023-10-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2023/10/01/macos-web-apps</id>
   <content type="html">&lt;p&gt;With the release of macOS Sonoma and Safari 17.0 earlier this week, we can now &lt;a href=&quot;https://support.apple.com/en-us/HT213583&quot;&gt;add web apps to the dock&lt;/a&gt;. Here’s a brief rundown of my experience testing them and customizing how &lt;a href=&quot;https://pierre.co&quot;&gt;Pierre&lt;/a&gt; appears when added to the dock.&lt;/p&gt;

&lt;p class=&quot;img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/pierre-file-explorer-light.png&quot; alt=&quot;Dockable web apps&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;mt-n2 small muted&quot;&gt;A look at Pierre’s file explorer when using the new dockable web apps in macOS Sonoma.&lt;/p&gt;

&lt;h2 id=&quot;adding-to-the-dock&quot;&gt;Adding to the dock&lt;/h2&gt;

&lt;p&gt;First, a brief intro how to add to the dock. Click the Share icon and select &lt;strong&gt;Add to dock&lt;/strong&gt;, or choose File &amp;gt; Add to Dock… from the menu bar.&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/add-to-dock.png&quot; alt=&quot;Add to dock&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can configure name, URL, and icon as soon as you create the web app. Additional options can be found in the web app’s Settings.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Name&lt;/li&gt;
  &lt;li&gt;URL&lt;/li&gt;
  &lt;li&gt;Icon&lt;/li&gt;
  &lt;li&gt;Show navigation controls: toggles the back and forward buttons in the title bar&lt;/li&gt;
  &lt;li&gt;Show color in the title bar: toggles macOS’s default title bar styling to matching the page &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-color&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also some privacy settings, but that’s not relevant to the discussion around styling obviously.&lt;/p&gt;

&lt;h2 id=&quot;web-app-limitations&quot;&gt;Web app limitations&lt;/h2&gt;

&lt;p&gt;Web apps are very slimmed down from Safari proper.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No address bar&lt;/li&gt;
  &lt;li&gt;Can’t open the web inspector directly, but can open it in Safari and then select the web app from the menu bar (Develop &amp;gt; Computer Name &amp;gt; Web App Name)&lt;/li&gt;
  &lt;li&gt;Can’t open links in new tabs, but can open links in new windows&lt;/li&gt;
  &lt;li&gt;Can’t use Safari extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And some other notable behavior:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Safari copies cookies to the web app at time of creation, and then keeps them separate after that&lt;/li&gt;
  &lt;li&gt;Web apps try to keep authentication flows within the app (for example, Google auth for Pierre worked within the web app without issue)&lt;/li&gt;
  &lt;li&gt;Autofill is available for passwords and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m sure there’s more, so let me know on Twitter/X if you find anything else.&lt;/p&gt;

&lt;h2 id=&quot;theme-color&quot;&gt;Theme color&lt;/h2&gt;

&lt;p&gt;Annoyingly, these web apps don’t seem to respect any theme color value. You can see if a site has a theme color in Safari by using the Compact tab layout. Shown here is &lt;a href=&quot;https://getbootstrap.com&quot;&gt;the Bootstrap homepage&lt;/a&gt; with the theme color applied.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sidebar: nice to see the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Open in web app&lt;/code&gt; banner for websites after you create them.&lt;/em&gt;&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/safari-compact-layout-issues.png&quot; alt=&quot;Theme color&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Compared to the same page in a new Safari web app, with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Show color in title bar&lt;/code&gt; option enabled. Missed opportunity.&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/web-app-no-theme.png&quot; alt=&quot;No theme color in app&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;theme-color&lt;/code&gt; meta tag has no affect:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;&amp;lt;!-- Doesn't work --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;theme-color&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#712cf9&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And configuring &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;theme_color&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;manifest.json&lt;/code&gt; doesn’t work either. Setting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background_color&lt;/code&gt; does though. Here’s Bootstrap’s current manifest file. Note that the name, icon, and start URL are all pulled from the manifest file, though.&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Bootstrap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;short_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Bootstrap&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;icons&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;android-chrome-192x192.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;192x192&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;android-chrome-512x512.png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;sizes&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;512x512&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;theme_color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;#7952b3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;background_color&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;#7952b3&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;display&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;standalone&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Checking the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Show color in title bar&lt;/code&gt; option currently seems to only pull from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;body&amp;gt;&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-color&lt;/code&gt;, which leads to some less than ideal results? Still unclear to me.&lt;/p&gt;

&lt;h2 id=&quot;styling&quot;&gt;Styling&lt;/h2&gt;

&lt;p&gt;In some situations, you’ll may want to tweak your site’s styling to better fit in with the web app itself. You can scope styles for this with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display-mode&lt;/code&gt; media query.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minimal-ui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;/* ... */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display-mode&lt;/code&gt; values seem to be supported:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fullscreen&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;standalone&lt;/code&gt; (no toolbar on macOS, home screen web app on iOS/iPadOS)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimal-ui&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;browser&lt;/code&gt; (default)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So far my only real use case for this was to add a border to the top of the site to separate it from the title bar, but that’s not very reliable because there’s no media query or control for detecting the title bar or anything else (unless a user toggling that changes the display mode?). For now I’m sticking with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimal-ui&lt;/code&gt; mode.&lt;/p&gt;

&lt;p&gt;Here they are in three super simple examples. Fullscreen and standlone appear to be the same on macOS, but on iOS/iPadOS there’s a difference as mentioned above. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;minimal-ui&lt;/code&gt; seems like the most practical for apps that required page navigation, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;standlone&lt;/code&gt; seems best for single page apps.&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/safari-web-app-fullscreen.png&quot; alt=&quot;Fullscreen web app&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/safari-web-app-standalone.png&quot; alt=&quot;Standalone web app&quot; /&gt;&lt;/p&gt;

&lt;p class=&quot;img-bg1 img-full&quot;&gt;&lt;img src=&quot;/uploads/2023/10/safari-web-app-minimal.png&quot; alt=&quot;Minimal UI web app&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;anything-else&quot;&gt;Anything else?&lt;/h2&gt;

&lt;p&gt;I only played with this for a day or so with &lt;a href=&quot;https://pierre.co&quot;&gt;Pierre&lt;/a&gt;, Bootstrap, and these little test apps. I’m curious what else others have learned thus far, so holler on Twitter/X. I’m also hoping to eventually dive into the notifications and badging more for Pierre and may write up some thoughts around that.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Bootstrap in Hugo with npm</title>
   <link href="https://markdotto.com/2022/05/23/bootstrap-hugo-npm/"/>
   <updated>2022-05-23T00:00:00+00:00</updated>
   <id>https://markdotto.com/2022/05/23/bootstrap-hugo-npm</id>
   <content type="html">&lt;p&gt;Up until &lt;a href=&quot;https://blog.getbootstrap.com/2022/05/13/bootstrap-5-2-0-beta/&quot;&gt;the latest redesign of the Bootstrap documentation&lt;/a&gt;, our blog and &lt;a href=&quot;https://icons.getbootstrap.com&quot;&gt;Icons&lt;/a&gt; sites were including Bootstrap’s compiled CSS and JavaScript via CDN. This worked great overall and gave, but I found myself needing and wanting more granular control over the final production assets. In particular, I wanted the source Sass files, but just the compiled JS for now. Despite using &lt;a href=&quot;https://gohugo.io&quot;&gt;Hugo&lt;/a&gt; for years now in Bootstrap’s docs, I’m a complete Hugo newbie, so I had no idea how to actually include Bootstrap with npm in a Hugo project. So I set out to fix that.&lt;/p&gt;

&lt;p&gt;The solution I used is straightforward, but I didn’t see many clear and concise answers on it outside some forum threads: use the Hugo mounts system. So, after you create your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;package.json&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;npm i bootstrap&lt;/code&gt;, you setup your Hugo config to pull from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;node_modules&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Here’s how it looks in our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;config.yml&lt;/code&gt; for the blog.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;mounts&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;           &lt;span class=&quot;s&quot;&gt;node_modules/bootstrap/scss&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;           &lt;span class=&quot;s&quot;&gt;assets/scss/bootstrap&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;source&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;           &lt;span class=&quot;s&quot;&gt;node_modules/bootstrap/dist/js/bootstrap.min.js&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;           &lt;span class=&quot;s&quot;&gt;assets/js/bootstrap.min.js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now we can import Bootstrap’s styles with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@import &quot;bootstrap/{filename}&quot;;&lt;/code&gt; as we’ve mounted Bootstrap’s source &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scss&lt;/code&gt; directory as part of our regular assets directory in Hugo. Here’s how the start of our stylesheet looks in the blog repo:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// src/assets/scss/style.scss&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/functions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/variables&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/maps&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/mixins&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/utilities&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/root&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/reboot&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/images&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/containers&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/grid&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/tables&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// @import &quot;bootstrap/forms&quot;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/buttons&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/transitions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;bootstrap/dropdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// @import &quot;bootstrap/button-group&quot;;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...and the rest of the Bootstrap imports&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From here, you can use the Sass functions, maps, mixins, mixins, and any component you need. &lt;a href=&quot;https://getbootstrap.com/docs/5.2/customize/sass/&quot;&gt;Read the Bootstrap Sass docs for more info.&lt;/a&gt; Importing the compiled CSS looks something like this:&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{{- $style := resources.Get &quot;scss/style.scss&quot; }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ $style.Permalink | relURL }}&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the JavaScript side, things are simpler since we’re just importing Bootstrap’s compiled and bundled JS file.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;{{ $bootstrapJs := resources.Get &quot;/js/bootstrap.min.js&quot; }}
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ $bootstrapJs.Permalink | relURL }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I decided I only really wanted the source Sass files and the compiled JavaScript for now. This way my dependencies and build steps would stay quite simple. To build your own JS bundle, you’d need your own bundler or an ESM shim like &lt;a href=&quot;https://github.com/guybedford/es-module-shims&quot;&gt;es-module-shim&lt;/a&gt;. Skipping that saved time and energy in keeping shipping the latest design updates.&lt;/p&gt;

&lt;p&gt;Lastly, there’s also &lt;a href=&quot;https://github.com/gohugoio/hugo-mod-bootstrap-scss&quot;&gt;the official Hugo module&lt;/a&gt; for Bootstrap’s SCSS and JS if you need it. I wanted to know how everything was working, so I went with the solution shown here instead of the module, but you should be good to go with either.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Fun with the dialog element</title>
   <link href="https://markdotto.com/2022/03/16/dialog-element/"/>
   <updated>2022-03-16T00:00:00+00:00</updated>
   <id>https://markdotto.com/2022/03/16/dialog-element</id>
   <content type="html">&lt;p&gt;There’s a new element in town and it’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;. Support for it &lt;a href=&quot;https://webkit.org/blog/12209/introducing-the-dialog-element/&quot;&gt;just landed in Safari&lt;/a&gt; with their newest update (v15.4) across all Apple’s devices. With that update, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element is now &lt;a href=&quot;https://caniuse.com/?search=dialog&quot;&gt;supported in every evergreen browser&lt;/a&gt;. It’s a great step forward for frameworks and libraries looking to make better use of native behaviors, but it’s also not without its limits.&lt;/p&gt;

&lt;h2 id=&quot;default-styles&quot;&gt;Default styles&lt;/h2&gt;

&lt;p&gt;Chrome, Safari, and Firefox all render dialogs similarly—black border, black text, white background. They’re all positioned absolutely without a predefined &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;z-index&lt;/code&gt;. There’s also no default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::backdrop&lt;/code&gt; styling. &lt;a href=&quot;https://codepen.io/emdeoh/pen/jOYPKPN&quot;&gt;Check out the CodePen demo.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2022/03/dialog-chrome.png&quot; alt=&quot;Dialog element in Chrome&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2022/03/dialog-safari.png&quot; alt=&quot;Dialog element in Safari&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2022/03/dialog-firefox.png&quot; alt=&quot;Dialog element in Firefox&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Only minor differences in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-width&lt;/code&gt; it seems.&lt;/p&gt;

&lt;p&gt;When there’s too much content, all dialogs will have an inner scroll. This makes adding a modal header a little annoying as you’ll have to ether add &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position: sticky&lt;/code&gt;, or create some custom components within to handle the scroll.&lt;/p&gt;

&lt;h2 id=&quot;functionality&quot;&gt;Functionality&lt;/h2&gt;

&lt;p&gt;By default, there’s no HTML magic you can use to toggle &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; elements—you have to write some JavaScript to open and close them programmatically. However, you can force a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; open with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;open&lt;/code&gt; attribute, which you can see in action in my &lt;a href=&quot;https://codepen.io/emdeoh/pen/jOYPKPN&quot;&gt;previously linked CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s what else you can do with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open regular, absolutely positioned dialogs with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/show&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;show()&lt;/code&gt; method&lt;/a&gt; if you don’t want a modal or backdrop&lt;/li&gt;
  &lt;li&gt;Open modal dialogs with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/showModal&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;showModal()&lt;/code&gt; method&lt;/a&gt; to open fixed position dialogs that block other page interactions&lt;/li&gt;
  &lt;li&gt;Close dialogs with &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/HTMLDialogElement/close&quot;&gt;the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;close()&lt;/code&gt; method&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Esc&lt;/code&gt; to close the dialog without any additional code&lt;/li&gt;
  &lt;li&gt;Style and animate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;::backdrop&lt;/code&gt; pseudo-element&lt;/li&gt;
  &lt;li&gt;Add a specific &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autofocus&lt;/code&gt; attribute inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; to automatically focus on it (otherwise, the first focusable element will be focused)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, because the modal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; backdrop is a pseudo-element, you cannot trigger JavaScript events off it. This makes it impossible to click the backdrop to dismiss the dialog. There’s likely a solution here with non-modal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;s, but I haven’t implemented a smooth solution to this yet.&lt;/p&gt;

&lt;p&gt;Regarding dialogs &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;autofocus&lt;/code&gt;-ing on the first focusable element, I suggest including a dismiss button near the top. When dialogs are too long and they scroll, it will automatically jump to that focused element. That means if you only have a dismiss button or single action at the bottom of the dialog, your visitors will miss the top portion.&lt;/p&gt;

&lt;h2 id=&quot;suggested-styling&quot;&gt;Suggested styling&lt;/h2&gt;

&lt;p&gt;Dialogs leave a lot to be desired with that default styling, but they are just as style-able as any other element. I put together a &lt;a href=&quot;https://codepen.io/emdeoh/pen/NWXPJOy&quot;&gt;CodePen demo&lt;/a&gt; that shows some suggested styles and implements easy toggling and closing via JavaScript.&lt;/p&gt;

&lt;p class=&quot;codepen&quot; data-height=&quot;400&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;NWXPJOy&quot; data-user=&quot;emdeoh&quot; style=&quot;height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/emdeoh/pen/NWXPJOy&quot;&gt;
  Using the &amp;lt;dialog&amp;gt; element&lt;/a&gt; by Mark Otto (&lt;a href=&quot;https://codepen.io/emdeoh&quot;&gt;@emdeoh&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Most dialogs include an inner header element with title and dismiss button, so I’ve implemented the same into &lt;a href=&quot;https://codepen.io/emdeoh/pen/NWXPJOy?editors=0100&quot;&gt;my CodePen demo&lt;/a&gt;. I’ve also the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position: sticky&lt;/code&gt; style I mentioned earlier to the dialog header so that when the dialog has an inner scroll, the dialog title and dismiss button are always visible. The dismiss button here also traps that default autofocus. Lastly, the backdrop is styled with a translucent &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-color&lt;/code&gt; and a quick little fade-in animation.&lt;/p&gt;

&lt;p&gt;Lastly, I made it all dark mode friendly with the help of some CSS variables and the &lt;a href=&quot;/2018/11/05/css-dark-mode/&quot;&gt;prefers-color-scheme media query&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;show-and-hide&quot;&gt;Show and hide&lt;/h2&gt;

&lt;p&gt;On the JS side, showing and hiding the dialog is easy enough. In my demo, this is accomplished with data attributes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-toggle&lt;/code&gt; is added to any triggering element and it’s value is the specified target &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-close&lt;/code&gt; is a boolean attribute that finds the nearest &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; to hide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the complete JS in action.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;[data-toggle]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;closers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;[data-close]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data-toggle&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showModal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;closers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;dialog&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;closest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;dialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see it all &lt;a href=&quot;https://codepen.io/emdeoh/pen/NWXPJOy&quot;&gt;in the demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;details-element&quot;&gt;Details element&lt;/h2&gt;

&lt;p&gt;Before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; support for Safari dropped this week, I was playing with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;details&amp;gt;&lt;/code&gt; element to build dropdowns and modals. It was definitely a fun and worthwhile experiment, and there’s a lot more I want to explore here around keyboard navigation and better modal styling/positioning. For now though, it’s a good comparison to the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; element and how you can create custom HTML elements.&lt;/p&gt;

&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;QWOVPVK&quot; data-user=&quot;emdeoh&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/emdeoh/pen/QWOVPVK&quot;&gt;
  Modals, dropdowns, and more&lt;/a&gt; by Mark Otto (&lt;a href=&quot;https://codepen.io/emdeoh&quot;&gt;@emdeoh&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codepen.io/emdeoh/pen/QWOVPVK&quot;&gt;Check it out on CodePen.&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dialog&quot;&gt;MDN: The dialog element&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://webkit.org/blog/12209/introducing-the-dialog-element/&quot;&gt;Introducing the dialog element&lt;/a&gt; (in Safari/Webkit)&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Horizontal scrolling nav</title>
   <link href="https://markdotto.com/2022/03/10/horizontal-scrolling-nav/"/>
   <updated>2022-03-10T00:00:00+00:00</updated>
   <id>https://markdotto.com/2022/03/10/horizontal-scrolling-nav</id>
   <content type="html">&lt;p&gt;Continuing with my JavaScript fun, I wanted to do an updated pass on the horizontal navs I’ve previously built for both GitHub Mobile (prior to the current responsive version and native apps) and this &lt;a href=&quot;https://getbootstrap.com/docs/5.1/examples/offcanvas-navbar/&quot;&gt;Bootstrap dashboard example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goal? Build a responsive horizontal navigation with an overflow scroll that automatically scrolls the active nav link into view. The responsive part is that the navigation links scroll horizontally—easy enough, and scales decently well across all viewports. The scrolling part and active link setting is done in JS and, thanks to work on the upcoming redesign of Bootstrap’s docs, relatively straightforward.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codepen.io/emdeoh/pen/eYeQjbq&quot;&gt;Here’s the final demo via CodePen.&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;codepen&quot; data-height=&quot;500&quot; data-default-tab=&quot;result&quot; data-slug-hash=&quot;eYeQjbq&quot; data-user=&quot;emdeoh&quot; style=&quot;height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/emdeoh/pen/eYeQjbq&quot;&gt;
  Scrolling nav&lt;/a&gt; by Mark Otto (&lt;a href=&quot;https://codepen.io/emdeoh&quot;&gt;@emdeoh&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Here’s a look at what’s under the hood. For the HTML, I’m using the barebones: a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, and the nav links. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; is what scrolls, while the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; holds the links to a single line at all times.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;header&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Demo&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;nav&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Home&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;World&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Politics&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Business&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Opinion&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;active&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Tech&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Science&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Health&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Sports&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Arts&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Books&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Style&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Food&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;li&amp;gt;&amp;lt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Travel&lt;span class=&quot;nt&quot;&gt;&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The CSS for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; get a little clever, though. I set a fixed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;height&lt;/code&gt; (equalling that of the computed link height) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;overflow-y&lt;/code&gt; on the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;nav&amp;gt;&lt;/code&gt; to “crop” the links within. But, that doesn’t stop the annoyance of scrollbars appearing on scroll and thus covering up the links. So, among some additional baseline styles, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; has a large &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;padding-bottom&lt;/code&gt; value to push any visible scrollbar out of sight. This has it’s own usability concerns—scrollbars show that something can scroll, how much content there is, etc—but there’s no elegant way to address this across all browsers and devices.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;nav&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;relative&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;z-index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;.5rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;overflow-y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;scroll-behavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;flex-wrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nowrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;.5rem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;margin-block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;overflow-x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;list-style&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;white-space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nowrap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the JavaScript side, we get started with querying for our selector, check if it exists in the page, and set some variables for the navigation links and active link.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;navLinks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activeLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Our first line of JS then is to immediately (on page load) scroll the active link into view of the containing element. In the CodePen, I set a link that should be offscreen as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.active&lt;/code&gt; element so anyone can see the scroll happen on page load. During my work on the Bootstrap docs, I found a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView&quot;&gt;helpful JS method&lt;/a&gt; for this, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrollIntoView&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;navLinks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activeLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;activeLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollIntoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;behavior&lt;/code&gt; tells the browser how to animate the scroll while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;inline&lt;/code&gt; tells the browser to align the scroll horizontally. (For vertical alignment, if needed, there’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;block&lt;/code&gt; parameter.) From here, we need to add an event listener to each nav link to set the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.active&lt;/code&gt; class and scroll the clicked link into view. This last bit of code could be cleaned up with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scrollIntoView&lt;/code&gt; function to de-dupe that line, but it didn’t feel worthwhile at the moment and adds a little more JS.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;nav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;navLinks&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;nav a&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;activeLink&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;activeLink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollIntoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;navLinks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;navLinks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;active&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;link&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollIntoView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;behavior&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;smooth&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Put it all together, you have a functional side-scrolling, responsive navigation. You may not even need the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.active&lt;/code&gt; class toggling, but it completes the demo here, so I’ve included it for the sake of completeness.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Toggling classes with JavaScript</title>
   <link href="https://markdotto.com/2022/03/02/toggling-classes-js/"/>
   <updated>2022-03-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2022/03/02/toggling-classes-js</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://twitter.com/mdo/status/1483871584267866115?s=21&quot;&gt;During my recovery&lt;/a&gt; I’ve made it a point to double down on improving my rather limited JavaScript skills. Courses have been helpful, but it seems that no matter the course, I do my best learning by making things myself. So I’ve been tinkering around and trying to build some new projects.&lt;/p&gt;

&lt;p&gt;My latest experiment was to build something that allows me to toggle a class on an element with a particular &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;button&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-toggle-target=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;#example&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-toggle-class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;blue&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  Toggle
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;example&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  This element will have the &lt;span class=&quot;nt&quot;&gt;&amp;lt;code&amp;gt;&lt;/span&gt;.blue&lt;span class=&quot;nt&quot;&gt;&amp;lt;/code&amp;gt;&lt;/span&gt; class toggled on it.
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The gist is that I want to use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;button&amp;gt;&lt;/code&gt; to toggle any class I want on another element of my choosing, all using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; attributes so that it’s infinitely flexible and functional in any context.&lt;/p&gt;

&lt;p&gt;Nothing big, but something I knew I wanted to demo it for the Bootstrap team so we could add a &lt;a href=&quot;https://github.com/twbs/bootstrap/pull/35872&quot;&gt;potentially new component in Bootstrap&lt;/a&gt;. After seeing what my original demo turned into with that pull request, I realized I had set my sights too low. Instead of toggling classes with a target with only an ID, why not specify targets by classes, attribute, or any other selector? So I rebuilt it to do just that.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://codepen.io/emdeoh/pen/VwrGzVN&quot;&gt;Here’s the final demo via CodePen.&lt;/a&gt;&lt;/p&gt;

&lt;p class=&quot;codepen&quot; data-height=&quot;300&quot; data-default-tab=&quot;html,result&quot; data-slug-hash=&quot;VwrGzVN&quot; data-user=&quot;emdeoh&quot; style=&quot;height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;&quot;&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/emdeoh/pen/VwrGzVN&quot;&gt;
  Toggle anything via data-attribute&lt;/a&gt; by Mark Otto (&lt;a href=&quot;https://codepen.io/emdeoh&quot;&gt;@emdeoh&lt;/a&gt;)
  on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;script async=&quot;&quot; src=&quot;https://cpwebassets.codepen.io/assets/embed/ei.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Here’s a walk through the JavaScript I wrote.&lt;/p&gt;

&lt;p&gt;First, we find all the elements that have the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data-toggle-target&lt;/code&gt; attribute so we can trigger our JavaScript on them.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[data-toggle-target]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Second, we add a quick check to see if there are any matching elements with that selector. This way our JavaaScript will only run if there are any elements to actually toggle.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From there, we use a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forEach&lt;/code&gt; loop to execute code against every matching instance of our selector from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toggler&lt;/code&gt; var. Within that loop, we then access the data attributes so we can use them later.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data-toggle-target&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggleClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data-toggle-class&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, we add an event listener to eacch toggling element (aka, the button) that toggles the specified class from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;toggleClass&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;[data-toggle-target]&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;toggler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data-toggle-target&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;toggleClass&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;data-toggle-class&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;click&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;targets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;classList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toggleClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If I had to improve things further, I’d like the trigger to be customizable to click, change (for form elements), hover, and focus. I’d also consider toggling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;id&lt;/code&gt;s and other selectors on the target element. Maybe in another post and experiment.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Diffing Sass maps</title>
   <link href="https://markdotto.com/2021/09/16/sass-map-diff/"/>
   <updated>2021-09-16T00:00:00+00:00</updated>
   <id>https://markdotto.com/2021/09/16/sass-map-diff</id>
   <content type="html">&lt;p&gt;I’ve been working on some baseline Sass tests for Bootstrap and had the need to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff&lt;/code&gt; two different Sass maps—the expected and the actual. &lt;a href=&quot;https://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; provides thousands of &lt;a href=&quot;https://github.com/twbs/bootstrap/blob/main/scss/_variables.scss&quot;&gt;default variables and several default Sass maps&lt;/a&gt; that are extended and reused under the premise of improved customization. What we’ve run into is some Sass limitations that forced us to make a few architectural changes.&lt;/p&gt;

&lt;p&gt;The main problem isn’t the limitation—that once a variable or map has been &lt;em&gt;used&lt;/em&gt;, it cannot be modified later—but rather that we weren’t testing for this enough. With that in mind, I set out to try some homegrown tests for how to compare what we expected to happen in our Ssas with what’s actually happening.&lt;/p&gt;

&lt;p&gt;This post is a rundown of what I tried out and where I ended up. To start, let’s assume these are our two maps.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// What we want to see&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;primary&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;secondary&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;info&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;warning&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;danger&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;light&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;dark&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;custom&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// What we're actually seeing&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;primary&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;secondary&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;success&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;info&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;warning&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;danger&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;compare-via-debug&quot;&gt;Compare via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@debug&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Intitially I just needed to know that two maps—the expected and the actual—matched without any warning or error in the CLI. That’s easy enough with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@debug&lt;/code&gt; and showing the map keys.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;The following maps should be the same, ending with the custom key.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which outputs the following:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Debug: The following maps should be the same, ending with the custom key.
Debug: &lt;span class=&quot;s2&quot;&gt;&quot;primary&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;secondary&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;success&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;info&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;warning&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;danger&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;light&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;dark&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;custom&quot;&lt;/span&gt;
Debug: &lt;span class=&quot;s2&quot;&gt;&quot;primary&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;secondary&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;success&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;info&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;warning&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;danger&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is helpful for manually checking if something is looking right, but not the best for proactively flagging an issue mid pull request.&lt;/p&gt;

&lt;h2 id=&quot;adding-in-warn&quot;&gt;Adding in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@warn&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Making use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@warn&lt;/code&gt;—which one could configure to fail a CI build—allows us to compile the entire Sass file and output all the issues to the CLI. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@error&lt;/code&gt; wouldn’t work for this as it’d stop the compiling at the first error.&lt;/p&gt;

&lt;p&gt;Here I setup an actual condtion—these two maps must equal one another. If they don’t, warn me and show me the difference.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@warn&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Keys in $colors don't match expected output.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Expected: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Actual:   &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which outputs the following:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Warning: Keys &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt; don&lt;span class=&quot;s1&quot;&gt;'t match expected output.
  test/index.scss 31:3  root stylesheet

Debug: Expected: &quot;primary&quot;, &quot;secondary&quot;, &quot;success&quot;, &quot;info&quot;, &quot;warning&quot;, &quot;danger&quot;, &quot;light&quot;, &quot;dark&quot;, &quot;custom&quot;
Debug: Actual:   &quot;primary&quot;, &quot;secondary&quot;, &quot;success&quot;, &quot;info&quot;, &quot;warning&quot;, &quot;danger&quot;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is great, but I still have to manually make the comparison for what’s different between expected and actual. To improve that, I needed to diff the two maps somehow.&lt;/p&gt;

&lt;h2 id=&quot;creating-diff-map&quot;&gt;Creating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff-map&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;There’s no built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map-diff&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map.diff&lt;/code&gt; feature in Sass, so I wrote a basic function to get me close enough. This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;diff-map&lt;/code&gt; function removes the keys found in both maps and shows me what’s left over in the expected map.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;diff-map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$actual-keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@each&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$actual-keys&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;diff-map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which outputs the following:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Debug: &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;light&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;dark&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;, &lt;span class=&quot;s2&quot;&gt;&quot;custom&quot;&lt;/span&gt;: &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Okay, now we’re getting somewhere. This doesn’t account for a situation though in which we have &lt;em&gt;more&lt;/em&gt; keys in the output than the expected map.&lt;/p&gt;

&lt;h2 id=&quot;improving-the-function&quot;&gt;Improving the function&lt;/h2&gt;

&lt;p&gt;Next I updated the function to ensure a diff happens in either direction. I added some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@if&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@else&lt;/code&gt; statements to ensure that the larger map (determined via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;length($map)&lt;/code&gt;) has it’s duplicate keys removed and we don’t end up with negative numbers. From there, we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@debug&lt;/code&gt; to print the number of remaining keys and list them.&lt;/p&gt;

&lt;p&gt;This iteration of the function isn’t the prettiest, but it’s effective. &lt;em&gt;Side note: there’s no real way to get a Sass map’s “name”, just it’s array of keys. Super sad.&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@function&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;diff-map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Maps have no differences.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;@else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Actual has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; more &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$keyword&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; than expected.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;@else&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$keyword&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;keys&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;key&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Actual has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$difference&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; fewer &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$keyword&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; than expected.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;$actual-keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$actual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;@each&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$actual-keys&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;@return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;@debug&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;diff-map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$expected-colors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which outputs the following:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Warning: Keys &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$colors&lt;/span&gt; don&lt;span class=&quot;s1&quot;&gt;'t match expected output.
    test/index.scss 154:3  root stylesheet

test/index.scss:188 Debug: Actual has 3 fewer keys than expected.
test/index.scss:199 Debug: (&quot;light&quot;: &quot;&quot;, &quot;dark&quot;: &quot;&quot;, &quot;custom&quot;: &quot;&quot;)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The debug statements in the CLI tell me that there are three fewer keys than expected and succinctly lists them out.&lt;/p&gt;

&lt;p&gt;I’m not done with this yet, but wanted to at least share what I stumbled into. Ideally this function could be improved to also account for more situations in which maps can be compared (e.g., actual and expected have unique keys).&lt;/p&gt;

&lt;p&gt;Check it out in &lt;a href=&quot;https://github.com/twbs/bootstrap/pull/34967&quot;&gt;this pull request in the Bootstrap repo&lt;/a&gt; and let me know what you think!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Learning CSS with utilities</title>
   <link href="https://markdotto.com/2021/08/10/learning-with-utilities/"/>
   <updated>2021-08-10T00:00:00+00:00</updated>
   <id>https://markdotto.com/2021/08/10/learning-with-utilities</id>
   <content type="html">&lt;p&gt;One of the premises behind &lt;a href=&quot;https://getbootstrap.com/docs/5.1/utilities/&quot;&gt;Bootstrap’s utilities&lt;/a&gt; is that each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;property: value&lt;/code&gt; pairing is attached to a class named after that pair—&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.property-value&lt;/code&gt;. Because of this pattern, creating and using utilities is an incredibly effective technique for learning CSS.&lt;/p&gt;

&lt;p&gt;When I wasn’t as familiar with flexbox, the &lt;a href=&quot;https://css-tricks.com/snippets/css/a-guide-to-flexbox/&quot;&gt;CSS-Tricks cheat sheet&lt;/a&gt; was indispensable, but I still found myself having to go back to it time and time again. &lt;a href=&quot;https://css-tricks.com/snippets/css/complete-guide-grid/&quot;&gt;Same with CSS Grid.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally added in v4 and refined in v5, Bootstrap has &lt;a href=&quot;https://getbootstrap.com/docs/5.1/utilities/flex/&quot;&gt;flexbox utilities&lt;/a&gt; and a &lt;a href=&quot;https://getbootstrap.com/docs/5.1/layout/grid/&quot;&gt;flexbox-based grid&lt;/a&gt; to use flexbox instead of floats. With the need for a slew of new supporting utilities, I taught myself flexbox by writing out every new class we’d need.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;.d-flex&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.flex-row&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.flex-column&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.justify-content-center&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;justify-content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.align-items-center&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;align-items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// etc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Writing all these out by hand for v4 gave me the muscle memory to remember specific patterns and behaviors for flexbox properties and values. It’s incredibly helpful that learning Bootstrap (and Tailwind, Rebass, Atomic, etc) is very much akin to learning CSS itself. Regardless of the tooling, you have to learn the properties and values, so why not get in the habit of writing them from the start?&lt;/p&gt;

&lt;p&gt;Utility driven frontend isn’t going anywhere, and neither is component driven frontend. They ebb and flow, and if you can understand what’s underneath them, you’re in the best position to learn any other tools and languages.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Force pushing to different Git remotes</title>
   <link href="https://markdotto.com/2021/07/27/force-push-remotes/"/>
   <updated>2021-07-27T00:00:00+00:00</updated>
   <id>https://markdotto.com/2021/07/27/force-push-remotes</id>
   <content type="html">&lt;p&gt;My Git/GitHub workflow has &lt;a href=&quot;/2020/03/24/git-reset/&quot;&gt;continued to evolve&lt;/a&gt; and now makes extensive use of rebasing and squashing instead of merge commits. While this is easy for branches in projects I maintain, it’s more complicated for forks of my projects. In those cases, I need to checkout, rebase, squash, and force push a branch to a different remote with a different branch name.&lt;/p&gt;

&lt;p&gt;Once you get your own copy of the fork’s branch locally and you’re ready to force push your rebased and/or squashed changes, here’s how you can push your changes from the terminal:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push remoteName localBranch:remoteBranch &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Before you push, you may need to add the fork as a new Git remote:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git remote add remoteName git:https://github.com/user/repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not familiar with force pushing, or squashing and rebasing? Consider exploring &lt;a href=&quot;https://docs.github.com/en/get-started/using-git/about-git-rebase&quot;&gt;the GitHub rebase docs&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Global CSS options with custom properties</title>
   <link href="https://markdotto.com/2020/05/20/global-css-options-custom-properties/"/>
   <updated>2020-05-20T09:00:00+00:00</updated>
   <id>https://markdotto.com/2020/05/20/global-css-options-custom-properties</id>
   <content type="html">&lt;p&gt;I’ve been toying around with some ideas for how to use custom properties (aka CSS variables) for global settings in a project. The idea is to provide control to designers/developers over consistent styles across multiple components. &lt;a href=&quot;https://codepen.io/emdeoh/pen/GRpQQXM?editors=1100&quot;&gt;See it in action in this CodePen&lt;/a&gt;, or read on for details.&lt;/p&gt;

&lt;p&gt;With Sass, this is pretty easy:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Global option&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$enable-shadows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Mixin that consumes the shadow&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@mixin&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$shadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@if&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$enable-shadows&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Put it to use&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;@include&lt;/span&gt; &lt;span class=&quot;nd&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;.5rem&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;By default now, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;s won’t be included in your compiled CSS, unless you change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$enable-shadows&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;. Doing this with custom properties isn’t as difficult as you might think, though.&lt;/p&gt;

&lt;p&gt;With custom properties, the logic is quite similar thanks to fallback values. If there’s a global &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-shadows&lt;/code&gt; option present, that will take precedence over the fallback value. To enable the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.component&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;, comment out or remove &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--enable-shadows&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Global option&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;--enable-shadows&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Put it to use&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;enable-shadows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;.5rem&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also go about this in another way by specifying a global shadow variable and overriding that at the component level with a utility or a modifier class.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Global option&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;--component-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;.5rem&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1rem&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Put it to use&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;component-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.remove-shadow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Because the custom property is within this ruleset,&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// it will only remove the shadow for this class&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;--component-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And with that, you have some basic control over global options in your CSS without the need for a preprocessor.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Publishing npm packages with dist tags</title>
   <link href="https://markdotto.com/2020/04/01/npm-dist-tags/"/>
   <updated>2020-04-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2020/04/01/npm-dist-tags</id>
   <content type="html">&lt;p&gt;Last month I published the next release of &lt;a href=&quot;https://icons.getbootstrap.com&quot;&gt;Bootstrap Icons&lt;/a&gt;, but I screwed up the distribution tags. Instead of publishing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest&lt;/code&gt; release, I published the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; release. That meant my &lt;em&gt;actual latest&lt;/em&gt; release wasn’t going to be the version folks get when they updated or installed the package today because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; is for upcoming pre-release versions. I’ve screwed this up in the past with &lt;a href=&quot;https://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; proper, too, because I never fully understood them.&lt;/p&gt;

&lt;p&gt;Until today, I didn’t even know these things were called distribution (dist) tags. TIL. And today I’m writing it down to remember it for next time.&lt;/p&gt;

&lt;p&gt;So how do you use these things or fix problems like this? Turns out &lt;a href=&quot;https://docs.npmjs.com/cli/dist-tag&quot;&gt;npm has you covered&lt;/a&gt; with some approachable docs, and you don’t need to release a new version or blow anything up in the process to fix a mistake like this.&lt;/p&gt;

&lt;p&gt;npm has &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dist-tag&lt;/code&gt; with some various options to review, add, and remove these tags:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm dist-tag add &amp;lt;pkg&amp;gt;@&amp;lt;version&amp;gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;tag&amp;gt;]
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm dist-tag &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &amp;lt;pkg&amp;gt; &amp;lt;tag&amp;gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm dist-tag &lt;span class=&quot;nb&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&amp;lt;pkg&amp;gt;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case, I had to remove the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;next&lt;/code&gt; dist tag and create a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;latest&lt;/code&gt; dist tag. It looked like this:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm dist-tag &lt;span class=&quot;nb&quot;&gt;rm &lt;/span&gt;bootstrap-icons next
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm dist-tag add bootstrap-icons@1.0.0-alpha3 latest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And with that, all was well. If you need a primer on managing alpha or beta releases, &lt;a href=&quot;https://medium.com/@kevinkreuzer/publishing-a-beta-or-alpha-version-to-npm-46035b630dd7&quot;&gt;check out this Medium article&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Faster rebasing with git reset</title>
   <link href="https://markdotto.com/2020/03/24/git-reset/"/>
   <updated>2020-03-24T00:00:00+00:00</updated>
   <id>https://markdotto.com/2020/03/24/git-reset</id>
   <content type="html">&lt;p&gt;Lately I’ve been needing to rebase and squash my commits more frequently. I’ve always been averse to doing anything like this because I’ve basically always screwed it up when using the command line. But thanks to &lt;a href=&quot;https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit&quot;&gt;this pro-tip I stumbled on&lt;/a&gt;, rewriting commits on an existing branch and PR has never been easier.&lt;/p&gt;

&lt;p&gt;Rather than do the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase -i&lt;/code&gt; dance, this approach resets your changes so you can selectively add what you need and write new commits. So much more approachable to me with my Git experience.&lt;/p&gt;

&lt;p&gt;Here’s the crux of the tip from &lt;a href=&quot;https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit&quot;&gt;the post&lt;/a&gt; that uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git reset&lt;/code&gt; to uncommit the differences between your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feature_branch&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Switch to the master branch and make sure you are up to date.&lt;/span&gt;
git checkout master
git fetch &lt;span class=&quot;c&quot;&gt;# this may be necessary (depending on your git config) to receive updates on origin/master&lt;/span&gt;
git pull

&lt;span class=&quot;c&quot;&gt;# Merge the feature branch into the master branch.&lt;/span&gt;
git merge feature_branch

&lt;span class=&quot;c&quot;&gt;# Reset the master branch to origin's state.&lt;/span&gt;
git reset origin/master

&lt;span class=&quot;c&quot;&gt;# Git now considers all changes as unstaged changes.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# We can add these changes as one commit.&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Adding . will also add untracked files.&lt;/span&gt;
git add &lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;
git commit
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;From here, add your files and changes in pieces as you like, write new commit messages, and then push your branch. If your branch is already pushed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;origin&lt;/code&gt;, you may need to force push (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push origin feature_branch --force&lt;/code&gt;). Be aware force pushing can have unintended consequences, so test these things out first in a safe environment.&lt;/p&gt;

&lt;p&gt;This page is nearly 10 years old and it’s still highly relevant. It also includes details on how to do a proper &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rebase&lt;/code&gt; for comparison. Hope it’s as helpful to you as it’s been to me with my open source projects and more.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Moving RSS</title>
   <link href="https://markdotto.com/2020/01/08/moving-rss/"/>
   <updated>2020-01-08T00:00:00+00:00</updated>
   <id>https://markdotto.com/2020/01/08/moving-rss</id>
   <content type="html">&lt;p&gt;Somehow I never migrated this site’s RSS feed from Feedburner. Well, nearly a decade after it was shut down by Google, I’m finally moving to a new feed that’s been around for years and just never shared.&lt;/p&gt;

&lt;p&gt;Please point your readers to &lt;a href=&quot;https://markdotto.com/atom.xml&quot;&gt;https://markdotto.com/atom.xml&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Null variables in Sass</title>
   <link href="https://markdotto.com/2019/08/30/null-sass-variables/"/>
   <updated>2019-08-30T00:00:00+00:00</updated>
   <id>https://markdotto.com/2019/08/30/null-sass-variables</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; is a large and complex frontend library with some powerful functionality and customization built-in. Occasionally though, we get asked to make things even more customizable for folks with more CSS properties and default variables.&lt;/p&gt;

&lt;p&gt;This is largely because Bootstrap’s CSS relies on some limited global inheritance of general styles (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line-height&lt;/code&gt;, and more), but developers and designers often want to customize things further. So we were typically faced with adding CSS we didn’t need at the outset, and that you &lt;em&gt;might&lt;/em&gt; need. This just didn’t seem right for any of us.&lt;/p&gt;

&lt;p&gt;Back &lt;a href=&quot;https://github.com/twbs/bootstrap/pull/28035&quot;&gt;in January&lt;/a&gt;, thanks to one of our maintainers &lt;a href=&quot;https://github.com/MartijnCuppens&quot;&gt;Martijn&lt;/a&gt;, we started using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; value default variables to combat that bloat while still increasing our level of customization.&lt;/p&gt;

&lt;p&gt;Here’s a basic example:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$body-text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$body-text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Won’t compile&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the Sass compiler will ignore the entire &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;property: value;&lt;/code&gt; declaration because the value is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt;. But, if someone customized this before compilation by overriding that default value, the CSS would compile. Here’s an example of how you’d override that default variable.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// First, override `!default` variables&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$body-text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Second, import Bootstrap&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;“&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bootstrap&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;”&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here’s how it compiles to CSS.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s also worth mentioning that these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; values can be used in mixins, too. Check out &lt;a href=&quot;https://blog.teamtreehouse.com/smarter-sass-mixins-null&quot;&gt;this old Treehouse article&lt;/a&gt; for details.&lt;/p&gt;

&lt;p&gt;Historically, more flexibility in our default styles meant more code for everyone, but with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;null&lt;/code&gt; value default variables, we can continue to provide more customization when warranted without knowingly adding bloat to our compiled CSS. I still owe Bootstrap a fresh pass at this to see what we can remove.&lt;/p&gt;

&lt;p&gt;Hopefully we can continue to find more techniques for increased customization and smaller file sizes. Please share if you have them!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CSS dark mode</title>
   <link href="https://markdotto.com/2018/11/05/css-dark-mode/"/>
   <updated>2018-11-05T00:00:00+00:00</updated>
   <id>https://markdotto.com/2018/11/05/css-dark-mode</id>
   <content type="html">&lt;p&gt;Dark mode is finally coming to CSS, and you can start experimenting with it thanks to &lt;a href=&quot;https://developer.apple.com/safari/technology-preview/&quot;&gt;Safari Technology Preview&lt;/a&gt;. With their latest release, the experimental browser includes support for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prefers-color-scheme&lt;/code&gt; media query. Variables in CSS are also coming, making dynamic light and dark modes for your visitors easier than ever.&lt;/p&gt;

&lt;p&gt;Here’s an abbreviated set of the variables and media query I’ve put to use for my sites.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--body-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fafafa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--body-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#555&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--link-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#222&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;py&quot;&gt;--link-color-hover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nd&quot;&gt;:root&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;--body-bg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#212529&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;--body-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#6c757d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;--link-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#dee2e6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;py&quot;&gt;--link-color-hover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should use this time to experiment with how you’d adapt your own styles to put &lt;a href=&quot;https://drafts.csswg.org/mediaqueries-5/#prefers-color-scheme&quot;&gt;the new media query&lt;/a&gt; to work. For example, picking the dark colors for my site wasn’t too difficult, but I found screenshots were far too intense for comfortable reading. A quick &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;opacity&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transition&lt;/code&gt; brings some added comfort while reading at night.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@media&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefers-color-scheme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;.75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;opacity&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;.5s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in-out&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;opacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>Shipping system fonts to GitHub.com</title>
   <link href="https://markdotto.com/2018/02/07/github-system-fonts/"/>
   <updated>2018-02-07T00:00:00+00:00</updated>
   <id>https://markdotto.com/2018/02/07/github-system-fonts</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;I’m finally publishing this blog post I drafted over a year ago. It was incomplete when I started to revisit it months ago, but I figured it’s better to share it now than sit on it forever. I’ve called out the additions and edits I made since that original draft. Some details are fuzzy, but the core remains intact.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last &lt;del&gt;week&lt;/del&gt; July, GitHub.com received a slightly updated design featuring more modern fonts. Instead of showing decades old fonts that don’t take advantage of newer, high DPI screens, or dynamic font rendering, we now try to serve the best font possible based on your operating system or device. Awesome!&lt;/p&gt;

&lt;p&gt;This posts explains why we made the change, how we coded and tested it, how we shipped the new fonts, and what we’ve done since initially making the move.&lt;/p&gt;

&lt;h2 id=&quot;before-and-after&quot;&gt;Before and after&lt;/h2&gt;

&lt;p&gt;Before we dive into the why, here’s a quick comparison of GitHub on macOS before and after the font change.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/98681/16757414/b449ed10-47c0-11e6-89b1-a06318b09520.png&quot; alt=&quot;before&quot; /&gt;
&lt;em&gt;You can really tell this is from well over a year ago given the light header, low contrast, and lack of saturation in all our colors.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/98681/16757415/b44e284e-47c0-11e6-83ee-221620e27a9e.png&quot; alt=&quot;after&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And now, with the dark header, color changes, and multiple product ships over a year later.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/98681/32348726-f92c9006-bfd1-11e7-9177-e55a8bb243c0.png&quot; alt=&quot;now&quot; /&gt;
&lt;em&gt;Compared to the previous figure, there’s clearly a stronger hierarchy and emphasis on key actions.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;why-change&quot;&gt;Why change&lt;/h2&gt;

&lt;p&gt;Our old font stack wasn’t exactly broken, but it &lt;em&gt;was&lt;/em&gt; decades old. That stack featured Arial and Helvetica for Windows and Mac users respectively. Helvetica was created in 1957 when the personal computer was a pipe dream. Arial was created in 1982 and is available on 95% of computers across the web. Millions, if not billions, of web pages currently use this severely dated font stack to serve much &lt;em&gt;younger&lt;/em&gt; content to much &lt;em&gt;younger&lt;/em&gt; browsers and devices.&lt;/p&gt;

&lt;p&gt;As display quality improves, so too must our use of those displays. System fonts like Apple’s San Francisco and Microsoft’s Segoe aim to do just that, taking advantage of retina screens, dynamic kerning, additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-weight&lt;/code&gt;s, and improved readability. If operating systems can take advantage of these changes, so too can our CSS.&lt;/p&gt;

&lt;p&gt;Speaking of which, the saying goes that the best UI is no UI. With system fonts, page content can feel more like it belongs on your particular computer or device. Pages on my iPhone rendered in San Francisco feel more like a page made just for my iPhone, and I know from experience when I use my Nexus, I feel the same with Roboto there.&lt;/p&gt;

&lt;h2 id=&quot;whats-changed&quot;&gt;What’s changed&lt;/h2&gt;

&lt;p&gt;While the move to the system font families is quite obvious visually, we (a combination of product designers and web designers before our Design Systems team was formed) shipped a few other changes.&lt;/p&gt;

&lt;p&gt;Here’s what’s new:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New fonts in our global &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-family&lt;/code&gt; for the “system fonts” approach.&lt;/li&gt;
  &lt;li&gt;Larger base &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-size&lt;/code&gt; for all pages, moving from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;13px&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;14px&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Improved type scale with clearer and more consistent heading sizes, weights, and line heights throughout.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these changes have given us a much easier to read site and a stronger, more considered system to build on moving forward.&lt;/p&gt;

&lt;h2 id=&quot;the-stack&quot;&gt;The stack&lt;/h2&gt;

&lt;p&gt;The new GitHub font stack has a handful of system fonts, plus some extras as fallback and emoji. Developers love their emoji like anyone else—maybe more.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apple-system&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;Roboto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Oxygen&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Ubuntu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Cantarell&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Fira Sans&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Droid Sans&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;s2&quot;&gt;&quot;Helvetica Neue&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Arial&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;s2&quot;&gt;&quot;Apple Color Emoji&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI Emoji&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI Symbol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This font stack has since been updated and iterated upon:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;apple-system&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BlinkMacSystemFont&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;n&quot;&gt;Helvetica&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Arial&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;s2&quot;&gt;&quot;Apple Color Emoji&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI Emoji&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Segoe UI Symbol&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s the rundown on what was originally included and what’s changed since we made the changes over a year ago:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-apple-system&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BlinkMacSystemFont&lt;/code&gt; target default fonts in Safari and Chrome on macOS and iOS.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segoe UI&lt;/code&gt; is explicitly named for all browsers on Windows 7+. Friendly side note, our Windows audience is either on Windows 7 or Windows 10—hardly anyone is on 8.x.&lt;/li&gt;
  &lt;li&gt;&lt;del&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Roboto&lt;/code&gt; is for Android and ChromeOS devices.&lt;/del&gt; We ended up removing Roboto because it caused issues in some distros of Linux. We definitely need to revisit it.&lt;/li&gt;
  &lt;li&gt;As fallback, Helvetica Neue and Arial are included. Fun fact, regular &lt;a href=&quot;https://snook.ca/archives/html_and_css/windows-subs-helvetica-arial&quot;&gt;Helvetica is actually aliased to Arial in the Windows registry&lt;/a&gt;, so you’ll never get regular Helvetica there anyway.&lt;/li&gt;
  &lt;li&gt;And lastly, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apple Color Emoji&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segoe UI Emoji&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Segoe UI Symbol&lt;/code&gt; ensure that we render the best emoji possible on macOS and Windows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, we originally had a few more fonts in there, but after shipping, we heard a ton of feedback from users with browsers, operating systems, and font settings we didn’t anticipate. This included Roboto, Oxygen, Ubuntu, Cantarell, Fira Sans, and Droid Sans. Interestingly enough, Linux users were the most upset at the change given Linux system fonts seem to be rather large and clunky, and their system fonts so inconsistent across distros.&lt;/p&gt;

&lt;h2 id=&quot;dealing-with-chrome&quot;&gt;Dealing with Chrome&lt;/h2&gt;

&lt;p&gt;&lt;del&gt;&lt;em&gt;Rather surprisingly, we’re well over a year past this original bug report and Chrome still doesn’t have this issue resolved.&lt;/em&gt;&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Turns out Chrome has fixed this with v64! Huzzah!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Sadly at the time of writing this, Chrome still hasn’t resolved a bug in how they render San Francisco in macOS. &lt;a href=&quot;https://bugs.chromium.org/p/chromium/issues/detail?id=627609&quot;&gt;You can follow the history of it on the Chromium bug report.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/98681/30940815-599aa6d2-a397-11e7-89ba-f1c73c3b7467.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://user-images.githubusercontent.com/98681/30940814-599a7d24-a397-11e7-8e74-052f5c7c5a85.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It’s subtle, but it’s definitely noticeable, especially when moving between other macOS apps and Chrome. Rather than utilizing the adaptive kerning of the new Apple font, Chrome applies a generic spacing multiplier across the entire font. This isn’t as noticeable for the SF Display variation of the font (which normally kicks in at 19pt and above), but it is obvious with the SF Text variant for body copy. Note how in the above screenshots the text wraps at different points.&lt;/p&gt;

&lt;p&gt;It’s definitely a bummer to see this bug stick around given so many of our website’s visitors are on Chrome. It’s at least somewhat good that Windows Chrome users outnumber the Mac ones, though!&lt;/p&gt;

&lt;h2 id=&quot;how-we-did-it&quot;&gt;How we did it&lt;/h2&gt;

&lt;p&gt;Rolling out code changes on GitHub can happen in a handful of ways, but for any sufficiently large project, we use feature flags to help. These flags allow us to enable a change on a per-user, per-team, per-organization, or per-repository basis with ease. It also allows us to “staff ship” something to every GitHub employee—this is how we chose to roll out the system font change.&lt;/p&gt;

&lt;p&gt;These feature flags are made accessible in our views, controllers, and more through a small Rails helper. (GitHub is one big Rails app right now in case you were wondering.) In our case, we had the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system_fonts&lt;/code&gt; feature flag attached to a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system_fonts_enabled?&lt;/code&gt; method. In practice, this allowed us to conditionally load an additional stylesheet that reset the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-family&lt;/code&gt;, provided our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-size&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line-height&lt;/code&gt; adjustments for the new fonts, and housed any component-level overrides to ensure the font changes didn’t break anything.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;%= stylesheet_bundle “system-fonts” if system_fonts_enabled? %&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Creating that stylesheet and it’s conditional inclusion was the quickest part of the entire project. Once the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-family&lt;/code&gt; was included there, we started browsing pages to see what was broken. That entire workflow really sucks in hindsight, but we don’t do visual diffing at GitHub (no reason why really) and it was the most straightforward path.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://cloud.githubusercontent.com/assets/6104/16347931/6dccfe1e-3a1d-11e6-8fe6-cfb53a8af22e.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As we found things that needed fixing, we put overriding styles in that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system-fonts.scss&lt;/code&gt; stylesheet with clear comments to explain why the override was needed. Here’s a snippet of what became a ~300 line stylesheet.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$body-font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$body-line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// To ensure text resides vertically right in the middle of our buttons, we bump&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// the line-height to 1.6. Otherwise, the button will be an odd-pixel height and&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// text will appear to sit too low.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.btn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.form-control&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$body-font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;.6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Forms need to have their padding match buttons otherwise they're different&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// heights when placed inline with one another.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.form-control&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;6px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Specificity wars; undo the above override so it doesn't fubar our header search.&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.header-search-wrapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.header-search-input&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Those code comments were super important early on as this override file was temporary from the get-go. It ensured the work we’d do later to remove this file was as smooth as possible and would ideally even lead to less CSS than when we started.&lt;/p&gt;

&lt;p&gt;After we shipped the change and merged it all into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;, we had did whole iterate-with-customer-feedback–and–clean-up-the-code dance. We adjusted the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-family&lt;/code&gt; and slowly started to move those overrides back to their original rules in our existing stylesheets. This was more problematic for some overrides than others, but in addition to removing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system-fonts.scss&lt;/code&gt; file, it led to a good amount of general CSS cleanup.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Before shipping, we staff shipped the font change to all GitHubbers to let it sync in and try to catch as many bugs as we could. We left it in staff mode for two weeks, making additional tweaks here and there before rolling it out to all our users.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;one-year-later&quot;&gt;One year later&lt;/h2&gt;

&lt;p&gt;My original draft of this post ended with the above section. Now, over a year later, I can add more context, talk about the iterative updates that went into the typography of GitHub.com, complain once more about this ridiculously old Chrome bug, and hype our Design Systems team.&lt;/p&gt;

&lt;p&gt;Near the beginning of 2017, we made a few other design changes to GitHub.com. Within a PR for that, I snuck in one more font change—adding SF Mono to our monospace font stack. It was a subtle change, but a good one for those who could benefit from it. Until the San Francisco fonts, no one on Mac or Windows had a shared sans-serif and monospace font experience. It’s small, and most folks likely don’t care about it, but it was cool to be able to merge that change six months later and complete the picture for macOS system fonts. Maybe we can help Windows and Linux soon!&lt;/p&gt;

&lt;p&gt;Several weeks after making the SF Mono change, we also looked into shipping an update to the font stack to clean up some of those browser-specific aliases. We merged the change after some quick testing and assumed everything was going to be spectacular. Thankfully our users are always quick to notice problems and were quick to point out to our Support teams that the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system-ui&lt;/code&gt; alias caused issues in WebKit and Blink browsers with non-English languages. We reverted the change back to the previous version and haven’t touched it since.&lt;/p&gt;

&lt;p&gt;After our Design Systems team officially formed up earlier this year, they continued to iterate on the code and documentation side of our typography. Making the change to the font stack and their various &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font-size&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line-height&lt;/code&gt; pairings was only the beginning. The team stepped up and overhauled all our Sass variables and mixins, and then documented it in our new upcoming style guide. Since making those changes, they’ve also heavily overhauled our CSS toolkit, Primer, to better organize all our CSS, including typography, for easier usage across other properties. As such, we were able to easily put our system fonts in more GitHub web projects, too. Woohoo!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Managing features in Bootstrap</title>
   <link href="https://markdotto.com/2015/09/28/bootstrap-features/"/>
   <updated>2015-09-28T00:00:00+00:00</updated>
   <id>https://markdotto.com/2015/09/28/bootstrap-features</id>
   <content type="html">&lt;p&gt;Several months ago someone asked me &lt;a href=&quot;https://github.com/mdo/feedback/issues/102&quot;&gt;how we manage and develop features&lt;/a&gt; in &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt;. Overall it’s rather ad hoc, but there are some specific guidelines we follow here and there.&lt;/p&gt;

&lt;h2 id=&quot;its-a-product&quot;&gt;It’s a product&lt;/h2&gt;

&lt;p&gt;The first thing to keep in mind is that we consider Bootstrap to be a real product. It has features, a development team, releases, and users. It has a mission of sorts—to make web design and development easier for folks. When we add or remove features, we’re attempting to balance that goal with our own experiences and interests, and those of our users.&lt;/p&gt;

&lt;p&gt;That mentality governs a lot of how we approach things with Bootstrap. We care a lot about it, we’re impacting real people’s lives, and we’re a small team having fun doing it. Feature wise, we figure out what we &lt;em&gt;could&lt;/em&gt; do, and then figure out what we &lt;em&gt;want&lt;/em&gt; to do and &lt;em&gt;how&lt;/em&gt; best to do it.&lt;/p&gt;

&lt;p&gt;In more practical terms, that means we don’t do something unless we believe we can do it well. And we say no to a lot of feature requests—focus and quality means more to us than implementing x, y, or z.&lt;/p&gt;

&lt;h2 id=&quot;general-feature-requests&quot;&gt;General feature requests&lt;/h2&gt;

&lt;p&gt;Tracking what to work on mostly happens on GitHub. The Bootstrap &lt;a href=&quot;https://github.com/twbs/bootstrap/issues&quot;&gt;issue tracker&lt;/a&gt; is our primary means of managing new features and updating existing ones. Anyone can ask us to implement something brand new or to extend an existing feature with an issue or pull request. Those we agree with or would like to get to are left open to implement and assigned a milestone for when to release. Others are commented on, cross referenced, and closed.&lt;/p&gt;

&lt;p&gt;Opening an issue or pull request doesn’t inherently mean we will do something though. We’re actually quite selfish about things. We build features we ourselves would like to see in other products and sites. There are tons of components we think make for bad experiences, shitty interactions, or are simply a pain for us to build and maintain (shoutout to datepickers).&lt;/p&gt;

&lt;p&gt;A side effect of that has also been that there’s an immensely large community out there doing all the things we can’t or don’t want to do. That’s huge for the folks that need and want those things, and I couldn’t be happier at the impact we’ve had there.&lt;/p&gt;

&lt;h2 id=&quot;major-releases&quot;&gt;Major releases&lt;/h2&gt;

&lt;p&gt;During the development of a major release (e.g., the forever upcoming v4), we don’t share much publicly until we’re ready for outside help and testing. This keeps us focused and involves the fewest decision makers as possible—just like any other product.&lt;/p&gt;

&lt;p&gt;We track features we want to build and overhaul in the next major release in private. We have two private repositories on GitHub for that—&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;twbs/team&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;twbs/derpstrap&lt;/code&gt;. Our team compiled a list of things we all wanted to see added, removed, or changed in v4 based on the trends we saw in the Bootstrap issues on GitHub. That list become our own master feature issue and have since used it to guide all our v4 work.&lt;/p&gt;

&lt;p&gt;Major releases are a chance for us to rewrite everything. We adopted this approach really early on to keep us interested in it over time. When you can experiment, have fun, and try new ideas on a longstanding proejct, it’s obviously more encouraging to continue working on it. So we change things up every now and then. Again, that’s selfish, but much more enjoyable long term.&lt;/p&gt;

&lt;h2 id=&quot;development&quot;&gt;Development&lt;/h2&gt;

&lt;p&gt;Regular development (minor and patch releases) happens in our issues and pull requests, either from us or contributors. New features usually end up becoming pull requests before making their way into the project.&lt;/p&gt;

&lt;p&gt;Overall our development flow looks like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;After we figure out what to build, we cut a branch and start adding the CSS, JS, and docs.&lt;/li&gt;
  &lt;li&gt;Open a pull request and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/cc&lt;/code&gt; the team and original issue opener.&lt;/li&gt;
  &lt;li&gt;Include any relevant information, screenshots, and a current state of affairs to tell folks where you’re at in the process.&lt;/li&gt;
  &lt;li&gt;Once tests pass and the feature is complete, we merge to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;We make a note in our ship list, an issue we open right after shipping the previous release to serve as a changelog.&lt;/li&gt;
  &lt;li&gt;When an upcoming version is almost ready to ship, we create the release on GitHub and share it with the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not every feature that sees a PR gets merged though. Sometimes we start to code a change and it just turns out bad. The code could suck, it could be too much code, or the feature could just not align with &lt;em&gt;n&lt;/em&gt; number of other things. We’re not shy when it comes to turning down large pull requests—we’ve got the entire project to think about first.&lt;/p&gt;

&lt;p&gt;Smaller contributions are also better than larger ones. Once a specific pull request passes a certain point—be it number of lines changed or sheer scope of changes—it’s neary impossible to review properly.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Honestly though, sometimes I skip a lot of those steps. In major releases, I cut a private branch or fork and just get down to it in the development branch. No branches, no pulls—just coding for days. With minor feature releases I sometimes just push right to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; as well, but that’s less ideal for history’s sake and should be discouraged.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;simple-and-focused&quot;&gt;Simple and focused&lt;/h2&gt;

&lt;p&gt;In short, we keep things simple and focused. Since Bootstrap is a side gig for most of us, a lightweight and approachable development process is very useful. We love helping folks build awesome stuff by building our own awesome stuff. It involves saying no a lot, and most importantly, thinking of Bootstrap as more than just an open source project.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Nesting in Sass and Less</title>
   <link href="https://markdotto.com/2015/07/20/css-nesting/"/>
   <updated>2015-07-20T00:00:00+00:00</updated>
   <id>https://markdotto.com/2015/07/20/css-nesting</id>
   <content type="html">&lt;p&gt;Nesting is supposed to make your CSS easier to read, extend, and maintain. For some situations, it does, but for designing CSS systems at scale, nesting your CSS is almost always a terrible idea. Allow me to explain with some general assumptions and examples.&lt;/p&gt;

&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions&lt;/h2&gt;

&lt;p&gt;No matter the build tool or preprocessor, there are a small set of general CSS guidelines I think most folks can agree on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Less compiled CSS is better.&lt;/li&gt;
  &lt;li&gt;Less &lt;em&gt;specific&lt;/em&gt; CSS is better.&lt;/li&gt;
  &lt;li&gt;Fewer selectors is better.&lt;/li&gt;
  &lt;li&gt;Smaller compiled file size is better.&lt;/li&gt;
  &lt;li&gt;Component-based CSS is better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Running with that, here are some examples of nesting.&lt;/p&gt;

&lt;h2 id=&quot;nesting-elements&quot;&gt;Nesting elements&lt;/h2&gt;

&lt;p&gt;I find this to be the most common form of nesting and is probably just fine for most &lt;em&gt;sites&lt;/em&gt;. It’s not necessarily bad, but nesting like this makes your CSS more specific. It also doesn’t force you to write reusable components, which is what you want for building most &lt;em&gt;apps&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Consider rewriting that code to something like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.parent-heading&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.parent-subheading&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.parent-permalink&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Those classes have lower specificity, more meaningful selectors, and are component-based.&lt;/p&gt;

&lt;h2 id=&quot;nesting-classes&quot;&gt;Nesting classes&lt;/h2&gt;

&lt;p&gt;Nested classes means you’re heading in the right direction, but are held back by overly specific CSS.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.parent-child&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.parent-child2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.parent-modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.parent-modifier2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You’ve got a parent element encapsulating all the children classes, but those children classes are already properly scoped as legit classes. Rewrite it just by removing the parent:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.parent-child&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.parent-child2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.parent-modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.parent-modifier2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The result is the same number of selectors, but with lower specificity.&lt;/p&gt;

&lt;h2 id=&quot;un-nesting-with-&quot;&gt;Un-nesting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;The &lt;em&gt;un-nesting&lt;/em&gt; example is perhaps the most confusing way to nest CSS.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.child&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.parent&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;When used at the end of a nested selector, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; puts everything to the left of it &lt;em&gt;before&lt;/em&gt; the parent selector. So the above example compiles to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.parent .child { }&lt;/code&gt;. This is confusing in a few ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt; puts that selector at the beginning of the top-most parent.&lt;/li&gt;
  &lt;li&gt;It’s the opposite of how regular nesting works.&lt;/li&gt;
  &lt;li&gt;It clouds your vision of the compiled CSS.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Rather than go that route, try something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.child&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.child-modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The result is a component-based approach with lower specificity and clearer insight into what your compiled CSS will be.&lt;/p&gt;

&lt;h2 id=&quot;bem-nesting-with-&quot;&gt;BEM nesting with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Nesting for BEM—or any other flavor CSS architecture—is helpful at first, but comes as a cost.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.block&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;__element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;While you’re saving a few bytes in your source file by not writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.block&lt;/code&gt; each time, you lose out on the ability search for your classes. When you’re debugging something with a browser’s Inspector, you only see the final, compiled class. So, when you need to search your code base for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.block__element&lt;/code&gt;, you won’t find it. That’s easy enough to get around, but that’s unnecessary cognitive overhead.&lt;/p&gt;

&lt;p&gt;Instead, keep it simple and just write it all out:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.block__element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.block--modifier&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Easy to read, easy to search, and with no sacrifice to your compiled CSS.&lt;/p&gt;

&lt;h2 id=&quot;nesting-pseudo-classes-with-&quot;&gt;Nesting pseudo-classes with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Nesting with pseudo-classes feels like the only practical way to nest your CSS.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.btn&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:focus&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:active&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What makes it different from the previous example is that this is all one element and class, just with different states. It’s not multiple half-classes that do different things. That means searching your codebase for it is super easy and more intuitive—just find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Moreover, and perhaps more helpful, is this makes your code more mixin- and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;extend&lt;/code&gt;-friendly (though the true merits of the latter are up for debate).&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;Bottom line? If you’re building pretty simple sites, nest to your heart’s content. However, if you’re building large apps or sites—Twitter, Bootstrap, GitHub, NY Times, etc—avoid it and keep your CSS simple, performant, and easy to parse.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing Primer</title>
   <link href="https://markdotto.com/2015/03/23/introducing-primer/"/>
   <updated>2015-03-23T00:00:00+00:00</updated>
   <id>https://markdotto.com/2015/03/23/introducing-primer</id>
   <content type="html">&lt;p&gt;Primer is GitHub’s internal CSS toolkit. It’s been the base coat for GitHub.com for years now, providing styles for our global typography, layout, tooltips, buttons, and more. Starting today, it’s open source.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://primercss.io&quot;&gt;&lt;img src=&quot;/uploads/2015/03/primer-docs.png&quot; alt=&quot;Primer docs&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Primer isn’t another large front-end framework, though. It’s rather limited in functionality and isn’t intended to replace something like Bootstrap. It will always be GitHub’s internal toolkit first, designed to help build &lt;em&gt;GitHubby&lt;/em&gt; things. That said, we love to share.&lt;/p&gt;

&lt;p&gt;Primer is licensed MIT, so you can basically do whatever you like with the source code. We’ll be a little stringent on merging new features to the project for the foreseeable future though. Longer term, we envision having a suite of Primer projects—one repository for each new component. More on that another time though.&lt;/p&gt;

&lt;p&gt;For now, head to GitHub to view the &lt;a href=&quot;https://github.com/primer/primer&quot;&gt;source code&lt;/a&gt; and read through the docs at &lt;a href=&quot;http://primercss.io&quot;&gt;http://primercss.io&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Recent projects</title>
   <link href="https://markdotto.com/2015/01/10/recent-projects/"/>
   <updated>2015-01-10T00:00:00+00:00</updated>
   <id>https://markdotto.com/2015/01/10/recent-projects</id>
   <content type="html">&lt;p&gt;It’s been awhile since I wrote about any of the recent projects I’ve worked on, so here’s a quick update.&lt;/p&gt;

&lt;h2 id=&quot;mdoml&quot;&gt;mdoml&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://mdo.github.io/mdoml&quot;&gt;&lt;img src=&quot;/uploads/2015/01/mdoml.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if you could augment HTML5’s current set of elements with your own? Well, as it turns out, you can. mdoml is an experiment in creating custom HTML elements based on today’s most common interface design components.&lt;/p&gt;

&lt;p&gt;Read about and try the experiment in &lt;a href=&quot;http://mdo.github.io/mdoml&quot;&gt;the live demo&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;ocean-dark-terminalapp-theme&quot;&gt;Ocean Dark Terminal.app theme&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mdo/ocean-terminal&quot;&gt;&lt;img src=&quot;/uploads/2015/01/ocean-dark-terminal.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I really love the &lt;a href=&quot;http://chriskempson.github.io/base16/#ocean&quot;&gt;Ocean color scheme&lt;/a&gt; from &lt;a href=&quot;https://github.com/chriskempson/base16&quot;&gt;base16&lt;/a&gt;. It’s included in the &lt;a href=&quot;http://kkga.github.io/spacegray/&quot;&gt;Spacegray UI theme&lt;/a&gt; for Sublime Text and Atom which I use and love. There are a ton of supported apps in the main repository, but not one for Terminal.app.&lt;/p&gt;

&lt;p&gt;Download and find out how to use it &lt;a href=&quot;https://github.com/mdo/ocean-terminal&quot;&gt;on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;github-wide&quot;&gt;GitHub wide&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mdo/github-wide&quot;&gt;&lt;img src=&quot;/uploads/2015/01/github-wide.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awhile ago I opened a pull request for GitHub.com to make the site entirely fluid. That is, instead of a fixed center aligned column, the site occupies the entire viewport. For a ton of reasons, we didn’t pursue it any futher than that pull request.&lt;/p&gt;

&lt;p&gt;Instead of abandoning the entire thing, I opted to open source the CSS as a custom user style. &lt;a href=&quot;https://github.com/mdo/github-wide&quot;&gt;Head to the repo&lt;/a&gt; for details.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using Sass with Jekyll</title>
   <link href="https://markdotto.com/2014/09/25/sass-and-jekyll/"/>
   <updated>2014-09-25T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/09/25/sass-and-jekyll</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Updated March 23, 2015: Removed mention of installing Sass gem as Jekyll ships with it’s own converter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While upgrading my &lt;a href=&quot;http://getpoole.com&quot;&gt;suite of Jekyll themes&lt;/a&gt; to utilize the built-in &lt;a href=&quot;http://sass-lang.com&quot;&gt;Sass&lt;/a&gt; compiler, I found the &lt;a href=&quot;http://jekyllrb.com/docs/assets/&quot;&gt;official docs&lt;/a&gt; and &lt;a href=&quot;https://github.com/jekyll/jekyll-sass-converter/tree/master/example&quot;&gt;example project&lt;/a&gt; a bit scattered and incomplete. As such, I decided to put this post together for my own reference down the line. Hopefully it helps you, too.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#assumptions&quot;&gt;Assumptions&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#install-sass&quot;&gt;Install Sass&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#create-a-sass-stylesheet&quot;&gt;Create a Sass stylesheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#link-your-stylesheet&quot;&gt;Link your stylesheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#using-sass-imports&quot;&gt;Using Sass imports&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#minification&quot;&gt;Minification&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#hosting-on-github-pages&quot;&gt;Hosting on GitHub Pages&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#example-project&quot;&gt;Example project&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;assumptions&quot;&gt;Assumptions&lt;/h2&gt;

&lt;p&gt;For brevity, this post assumes a couple things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You have an existing Jekyll project up and running, or know how to start one from scratch.&lt;/li&gt;
  &lt;li&gt;Your local Jekyll is using version 2.4.0 or better (check in Terminal with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll --version&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;You have some knowledge of Sass.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Got all that? Awesome, carry on.&lt;/p&gt;

&lt;h2 id=&quot;install-sass&quot;&gt;Install Sass&lt;/h2&gt;

&lt;p&gt;Nothing to install here. Jekyll ships with it’s own Sass converter, so you’re good to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait, Sass or Scss?&lt;/strong&gt; As far as I know, Jekyll includes support for both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sass&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scss&lt;/code&gt;. If you’re unfamiliar with the differences, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.sass&lt;/code&gt; allows you to omit curly braces. I recommend sticking with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scss&lt;/code&gt;—it’s less clever and more approachable.&lt;/p&gt;

&lt;h2 id=&quot;create-a-sass-stylesheet&quot;&gt;Create a Sass stylesheet&lt;/h2&gt;

&lt;p&gt;Create your Sass stylesheet wherever you like. At the top of the file, include a front matter comment, then add your styles after.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Front&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;matter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Jekyll&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;properly&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;reads&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Add&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;your&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;styles&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;here&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For the purpose of this post, I’m putting it within a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css/&lt;/code&gt; directory. Here’s what my typical Jekyll site’s directory looks like:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;jekyll-project/
├── _includes/
├── _layouts/
├── _posts/
└── css/
│   └── styles.scss
├── _config.yml
└── index.html&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Assuming that structure, Jekyll will compile your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;css/styles.scss&lt;/code&gt; file into a CSS file at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_site/css/styles.css&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;link-your-stylesheet&quot;&gt;Link your stylesheet&lt;/h2&gt;

&lt;p&gt;Now that we’ve got the CSS being built, the last step is including it in your site’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt;. Be aware you may need to tweak the path depending on your setup.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/css/styles.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At this point you’re essentially done—this the most basic setup for using Sass with Jekyll. Add you Sass in the source &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;styles.scss&lt;/code&gt; file and compile it simply by starting the Jekyll server.&lt;/p&gt;

&lt;h2 id=&quot;using-sass-imports&quot;&gt;Using Sass imports&lt;/h2&gt;

&lt;p&gt;Jekyll includes built-in support for using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@import&lt;/code&gt;s to compile multiple source files into one CSS file. Place your partial &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.scss&lt;/code&gt; files in the default directory, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_sass/&lt;/code&gt; and include them in your main Sass stylesheet like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-scss&quot; data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;#&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Front&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;matter&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Jekyll&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;properly&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;reads&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;---&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;Imports&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;base&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;layout&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can also change the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_sass/&lt;/code&gt; directory to a custom directory in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;sass_dir&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;_lib&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;minification&quot;&gt;Minification&lt;/h2&gt;

&lt;p&gt;Enable minification on your compiled CSS by updating your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; to include:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;compressed&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now when Jekyll compiles your Sass, you’ll have no whitespace in your CSS. Be sure to turn this on for production environments if file size is of any concern.&lt;/p&gt;

&lt;h2 id=&quot;hosting-on-github-pages&quot;&gt;Hosting on GitHub Pages&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://pages.github.com&quot;&gt;GitHub Pages&lt;/a&gt; has been built with Jekyll in mind—just push your Jekyll site to a branch named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; to get started. It includes support for compiling Sass (and CoffeeScript!) when you push a commit up.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Curious about what dependencies and versions are on GitHub Pages? &lt;a href=&quot;https://pages.github.com/versions/&quot;&gt;Check the versions page.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;example-project&quot;&gt;Example project&lt;/h2&gt;

&lt;p&gt;I’ve turned all this into a super basic &lt;a href=&quot;https://github.com/mdo/jekyll-example&quot;&gt;example Jekyll project&lt;/a&gt; and open sourced it on GitHub. It’s licensed MIT and includes everything mentioned above for setting up Sass with Jekyll.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Shipping GitHub's split diffs</title>
   <link href="https://markdotto.com/2014/09/04/shipping-githubs-split-diffs/"/>
   <updated>2014-09-04T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/09/04/shipping-githubs-split-diffs</id>
   <content type="html">&lt;p&gt;GitHub has been around for over six years, and in all that time there’s only been one mode for diffing code—the unified diff. Until yesterday, that is, when we &lt;a href=&quot;https://github.com/blog/1884-introducing-split-diffs&quot;&gt;shipped split diffs&lt;/a&gt;. Here’s how they look:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diff-genpop.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Similar to my post on &lt;a href=&quot;/2014/08/04/shipping-the-new-github-issues/&quot;&gt;shipping the new GitHub issues&lt;/a&gt;, I wanted to give some background on the how and why of shipping what until this week was our most requested feature.&lt;/p&gt;

&lt;h2 id=&quot;timing&quot;&gt;Timing&lt;/h2&gt;

&lt;p&gt;For as long as I’ve worked at GitHub, there was an unintentional Hacker News tradition for every major feature we shipped. No matter the ship, we’d most assuredly get a comment like:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Neat. When are they going to do split diffs?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The general sentiment was surely it couldn’t take this long to build split diffs, so why didn’t we just done it already? Well, as it turns out, there were &lt;strong&gt;many&lt;/strong&gt; great reasons why we couldn’t (or wouldn’t). To start:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Many GitHubbers never really used split diffs, so they didn’t see much value in building them into GitHub. I can’t blame anyone for that—either you’ve used and loved them, or you haven’t.&lt;/li&gt;
  &lt;li&gt;For the last two years, it was actually quite difficult to build. The code for diffs was quite complicated, all our JS depended on super specific HTML, and in general diffs were touchy on performance.&lt;/li&gt;
  &lt;li&gt;Lastly, and perhaps most importantly, we never just add something for the sake of adding it, especially a feature that impacts so much of our core offering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having worked at Twitter for two and a half years before GitHub, I spent much of my time in &lt;a href=&quot;https://www.reviewboard.org&quot;&gt;Reviewboard&lt;/a&gt;, a fantastic but ugly and slow code review tool that used split diffs. When I moved on to GitHub, I definitely missed the functionality, and it became one of pie in the sky type of features I wanted to help build.&lt;/p&gt;

&lt;h2 id=&quot;first-prototype&quot;&gt;First prototype&lt;/h2&gt;

&lt;p&gt;Six months after I joined GitHub, I finally gathered the courage to attempt just that. Much to my surprise at the time, it wasn’t actually &lt;em&gt;too&lt;/em&gt; bad to get started. Here’s what I ended up with:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diffs-v1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever looked under the hood of a GitHub diff, you’d notice we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;table&amp;gt;&lt;/code&gt;s to render them. Each line number and line of code is it’s own table cell. We use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data&lt;/code&gt; attributes and JavaScript to handle line numbers and diff context expansion (showing more of a diff’s file).&lt;/p&gt;

&lt;p&gt;Once I had a better handle on our diff views, and knowing they were &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;table&amp;gt;&lt;/code&gt;-based, I was able to see that the first and biggest step was to duplicate the existing code table cell. Then, I used some CSS-fu to collapse the “empty” cells on either side of the table.&lt;/p&gt;

&lt;p&gt;Easy-peasy. Or so I thought.&lt;/p&gt;

&lt;h2 id=&quot;prototype--production-ready&quot;&gt;Prototype ≠ production ready&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Ultimately, none of it could ship.&lt;/strong&gt; For a number of reasons, what I built 18 months ago was in no shape to be the underpinnings of a production-ready feature:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We were increasing the number of elements on the page by at least 33% (three existing cells for unified diffs, four for split).&lt;/li&gt;
  &lt;li&gt;Within those table cells there used to be a lot more markup. A &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;span&amp;gt;&lt;/code&gt; around every line number, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;pre&amp;gt;&lt;/code&gt; around every line of code, etc. That all adds up.&lt;/li&gt;
  &lt;li&gt;This prototype didn’t take into account how to actually switch between unified and split diffs, or if we’d do that at all.&lt;/li&gt;
  &lt;li&gt;It didn’t address diff expansion at all, and it turns out that code was completely dependent on the order of line number, line number, code for unified diffs.&lt;/li&gt;
  &lt;li&gt;It didn’t address code commenting in the slightest. How would comments work—one side, both sides, something else?&lt;/li&gt;
  &lt;li&gt;How would this impact the soon-to-be shipped prose diffs, which further complicated the diff code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It just wasn’t going to happen without some serious and dedicated developer help beyond my limited abilities. Once I realized that, I gave up and moved on to other things. No one else really picked it up from there, and I think I have an idea why.&lt;/p&gt;

&lt;p&gt;At the time, &lt;strong&gt;nothing shipped without a pull request and dedicated developer to push it through.&lt;/strong&gt; I had a branch, but never opened a pull request for it. Given that, I think folks assumed I’d finish it eventually, and so no one else jumped on it until I did again 18 months later.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Today, the process for proposing and shipping a brand new feature are much better. We have a loose product roadmap, folks in leadership positions, and a better ship list. This new process is part of why split diffs shipped so quickly.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;take-two&quot;&gt;Take two&lt;/h2&gt;

&lt;p&gt;Fast forward to two months ago. We had just finished putting together a first pass at a more formal roadmap and split diffs were on the list. The exact details of the feature were still up in the air, but it was just enough pressure to kickstart things.&lt;/p&gt;

&lt;p&gt;Given I was the last to prototype it, I started in on split diffs once more with a fresh branch. After a couple days I had another working prototype that was rather similar to the first:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diffs-v2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This time though, I pushed the branch and opened a pull request. I pinged a couple folks and got a developer assigned to the project. &lt;strong&gt;Three weeks, 65 commits, and two contributors later&lt;/strong&gt; my hacky second prototype turned into a staff shipped feature.&lt;/p&gt;

&lt;p&gt;Hell yeah.&lt;/p&gt;

&lt;h2 id=&quot;road-to-shipping&quot;&gt;Road to shipping&lt;/h2&gt;

&lt;p&gt;With that initial staff ship, we knew we were on the right track, but we had plenty of work to do before we could ship it to everyone. We had to refactor a lot of code and redesign a few key areas of the site to pull it off.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-diffs-add-comment.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I redesigned the “Add line comment” button to overlay the line number and code instead of overhanging on the edge, since we needed to go full-width for split diffs and a hanging icon on either side wasn’t going to cut it. It also provided an opportunity to clarify click areas throughout unified and split diffs.&lt;/p&gt;

&lt;p&gt;In addition to the refresh of the UI components, the JS for line commenting and diff expansion was completely overhauled so that it’d work the same across split and unified diffs.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diffs-pr1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We rewrote a ton of code for this, and it was all for the better honestly. On the HTML/CSS side, I refactored the code blobs (static files) and diffs to share more code.&lt;/p&gt;

&lt;p&gt;Previously, blobs were two table cells, one for all line numbers and one for all code lines. After the refactor, blobs and diffs were using the same table approach: one row for each line number and code cell.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diffs-pr2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Figuring out how to break the entire site’s layout on just a handful of pages was a bit of a challenge. For most views it’s as simple as removing a fixed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width&lt;/code&gt; and adding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;padding&lt;/code&gt;. However, in other areas like the pull request composer above, we needed to do some refactoring to avoid nested fixed widths.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/09/github-split-diffs-uxr.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We also conducted several casual user studies to gauge folks’ reactions to the interface, verbiage, performance, and more to verify our gut calls on how to build a “GitHubby split diff” feature. Ultimately the folks we talked to confirmed our own hunches—ship it!—and lined up a ton of next steps for us.&lt;/p&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;/h2&gt;

&lt;p&gt;I purposely avoided talking about a few aspects of this project, but hopefully what’s here gives you a good idea of what went into designing, developing, and shipping split diffs.&lt;/p&gt;

&lt;p&gt;A number of things were punted so we could ship as fast as possible. To name a few, we still need to polish up the transition from fixed-width to full-width across the site and there are some bugs around composing comments and switching diff modes.&lt;/p&gt;

&lt;p&gt;Bottom line? &lt;strong&gt;In exactly two months, we went from my pretty shitty pull request to a fully fledged, shipped feature.&lt;/strong&gt; That’s simply astounding to me given the scope of changes. I’m super proud of this first step and the team. I’m stoked for what’s next.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Shipping the new GitHub Issues</title>
   <link href="https://markdotto.com/2014/08/04/shipping-the-new-github-issues/"/>
   <updated>2014-08-04T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/08/04/shipping-the-new-github-issues</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-shipped.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We started work on the new GitHub Issues over nine months ago. It was a bit of a crazy ride, but I’m honestly stoked about what we shipped. For the quick low down on what shipped, &lt;a href=&quot;https://github.com/blog/1866-the-new-github-issues&quot;&gt;read the GitHub blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Given the length and scope of the project, I wanted to share more than that blog post and tell the story of how we went from a single pull request to &lt;a href=&quot;https://github.com/twbs/bootstrap/issues&quot;&gt;the shipped feature&lt;/a&gt; you see today.&lt;/p&gt;

&lt;p&gt;Buckle up.&lt;/p&gt;

&lt;h2 id=&quot;table-of-contents&quot;&gt;Table of contents&lt;/h2&gt;

&lt;p&gt;Instead of splitting the article, I figured I’d write until I couldn’t and just give y’all a helpful table of contents.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#why&quot;&gt;Why&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#use-it-to-improve-it&quot;&gt;Use it to improve it&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#metrics&quot;&gt;Metrics&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#logistics&quot;&gt;Logistics&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#nine-months&quot;&gt;Nine months!?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#who&quot;&gt;Who&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#working-together&quot;&gt;Working together&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#opening-a-pull-request&quot;&gt;Opening a pull request&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#determining-features&quot;&gt;Determining features&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#iterating&quot;&gt;Iterating&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#earliest-iterations&quot;&gt;Earliest iterations&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#aesthetics&quot;&gt;Aesthetics&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#searching-vs-filtering&quot;&gt;Searching vs. filtering&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#structure&quot;&gt;Structure&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#additional-views&quot;&gt;Additional views&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#settling-down&quot;&gt;Settling down&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#validating-our-ideas&quot;&gt;Validating our ideas&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#shipping-it&quot;&gt;Shipping it&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;why&quot;&gt;Why&lt;/h2&gt;

&lt;p&gt;Perhaps the most important question is why would we even work on Issues? And what exactly would we do with it? How did we know that it needed the love?&lt;/p&gt;

&lt;h3 id=&quot;use-it-to-improve-it&quot;&gt;Use it to improve it&lt;/h3&gt;

&lt;p&gt;We spend most of our time on issues at GitHub. Internally, &lt;strong&gt;we use the hell out of Issues for everything&lt;/strong&gt;. Have a problem with the office? Open an issue. They’re a written record, cheap and fast to create, and searchable. Between our extensive usage internally and the number of folks here contributing to open source projects, we’re some of the most prolific issues users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; There was no one thing that motivated us to do it. We just started to notice some things that could be better, like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It was starting to feel dated compared to other aspects of the site and enough folks spoke up about it.&lt;/li&gt;
  &lt;li&gt;The interface was a bit cluttered with nav and filters on the top, right, and left sides.&lt;/li&gt;
  &lt;li&gt;Searching for issues was an entirely different experience. We didn’t have a dedicated search for issues, so when you searched for a specific one, you left your repo’s issues list and landed on a search results page. From there you couldn’t triage any aspect of the issue until clicking into it.&lt;/li&gt;
  &lt;li&gt;We were missing a bunch of information on the issues and pull request lists—task list progress, milestone name, build status, etc.&lt;/li&gt;
  &lt;li&gt;At least two of us wanted to work on it, and we both were excited by the possible outcomes the more we talked about it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once we had that kind of feedback shared (you know, if you see something say something), and folks agreed that those were worthy problems to solve, we got to work writing code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For what it’s worth, this is just about how all product or redesign work goes on the GitHub.com side. Find a problem, propose a solution (usually with code), get feedback, and find a way to ship it. We’re looking into how we can improve this and apply a process or checklist to all great ships, but that’ll take some time.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;metrics&quot;&gt;Metrics&lt;/h3&gt;

&lt;p&gt;We didn’t spend much time looking at analytics or metrics for Issues before diving in, but we have historical data we can compare against. Throughout the project we tried to optimize our database reads and ensure we didn’t have extra HTML and CSS lying around, but that’s about as far as we got for the front-end performance stuff.&lt;/p&gt;

&lt;h2 id=&quot;logistics&quot;&gt;Logistics&lt;/h2&gt;

&lt;p&gt;Before I get to the good parts, first let me explain a few things about how all this went down logistically as it’s important to have a bit of context for this given our usual shipping speed.&lt;/p&gt;

&lt;h3 id=&quot;nine-months&quot;&gt;Nine months!?&lt;/h3&gt;

&lt;p&gt;So, first, why nine months?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We had two large related projects going on at the same time: the issues redesign (internally and hereby called Issues 3) and &lt;a href=&quot;https://github.com/blog/1767-redesigned-conversations&quot;&gt;our conversations redesign&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;The conversations redesign took our attention away from Issues 3 after a few weeks. Ultimately it derailed us for around three months while we iterated, shipped, and cleaned up after ourselves.&lt;/li&gt;
  &lt;li&gt;We had a bit of trouble keeping the two projects separate. We ended up blending some ideas and that also set us back.&lt;/li&gt;
  &lt;li&gt;We improved a ton of our infrastructure around search and issues performance.&lt;/li&gt;
  &lt;li&gt;We spent a lot of time trying things out for a week or so between bigger iterations. Our goal was workflow improvements, so we need to work with these ideas more so than other ships.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was a challenge for all of us—me in particular—at balancing two separate-but-related efforts. Crossing the &lt;strike&gt;streams&lt;/strike&gt; ships meant adding complexity, spinning our wheels, and losing sight of the specific end goal for each ship. I think we did an alright job of realizing that quickly enough and ended up getting a ton of work done.&lt;/p&gt;

&lt;h3 id=&quot;who&quot;&gt;Who&lt;/h3&gt;

&lt;p&gt;The Issues 3 core team was essentially three people: two developers and one designer/frontender (me). The extended team included our Ops and database folks, search engineers, and people from support and docs teams. Plus, dozens of others in the company who provided feedback via issues and pull requests throughout.&lt;/p&gt;

&lt;h3 id=&quot;working-together&quot;&gt;Working together&lt;/h3&gt;

&lt;p&gt;We found out really early on that all of us on the core team worked pretty damn well together. We moved fast, broke things, opened tons of pull requests and issues, called each other out on bullshit, propped each other for amazing ideas. Most of it happened fluidly and off the cuff. There was hardly anything formal about it until we were near ship time.&lt;/p&gt;

&lt;p&gt;Here are two examples of how most of our work was done.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-issue-example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Issues were opened with specific feedback by one of us (or others across the company), labels added, milestone set, and someone assigned. When we had fixes to deploy, we opened pull requests.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-pr-example.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We’d try to be as detailed as possible. We included screenshots, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/cc&lt;/code&gt;-ed the right folks (e.g., the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@github/issues&lt;/code&gt; team), and then quickly shipped it. Given the early work on Issues 3 was only team shipped, we could afford to screw things up every now and then because only we would be affected.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There was still a chance of screwing up other things mind you, and I may have done just that a couple times, but we were pretty well shielded.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In issues and pull requests, we’d use task lists whenever possible. Similar to full fledges issues, we’d try our best to be super clear and assignee folks or ask for help when we needed it.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-todos.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Those issues task lists were especially useful when we got closer to shipping and could use them to do production readiness reviews, check in with the docs team on how their updated screenshots were going, and review last minute tweaks or bug fixes.&lt;/p&gt;

&lt;p&gt;Put another way, &lt;strong&gt;we used GitHub Issues to build GitHub’s new Issues&lt;/strong&gt;, and it was pretty damn awesome.&lt;/p&gt;

&lt;h2 id=&quot;opening-a-pull-request&quot;&gt;Opening a pull request&lt;/h2&gt;

&lt;p&gt;Okay, now, back to the product work.&lt;/p&gt;

&lt;p&gt;A bunch of us had been talking about updating Issues for a long time, but it didn’t take off until &lt;a href=&quot;https://github.com/holman&quot;&gt;Holman&lt;/a&gt; opened the first pull request. (That’s often the case—some ideas just stall out without some code to kick them off.)&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-pr.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The first Issues 3 pull request was opened back in October of last year, and while the aesthetics and layout details changed a lot over time, the core idea never did. &lt;strong&gt;This would make search the interface.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The idea itself didn’t feel all that radical, but it did heavily influence the architectures and interface. Under the hood, we leaned into Elastic Search and MySQL to build out the functional tidbits. Today, Elastic Search powers all the custom search queries while MySQL handles the general issue and pull request listing and more.&lt;/p&gt;

&lt;p&gt;Interface wise, it’s pretty clear that search was the focus early on. That search bar was huge! Everything you did updated the search bar, and heck some things were (and still are) just easier when you type in the search input. I was honestly hesitant about this, but the team’s excitement kept us moving.&lt;/p&gt;

&lt;h2 id=&quot;determining-features&quot;&gt;Determining features&lt;/h2&gt;

&lt;p&gt;That first pull request had it’s own feature set: more search, triage mode (bulk actions), and faster access to issues. Along with that first iteration though came a bunch of spontaneous ideas from within our team as work progressed.&lt;/p&gt;

&lt;p&gt;Quite a few of the features we shipped with actually came organically out of that.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Search is obviously the huge feature focus in Issues 3, but the specifics were worked out as we went. We defined the search syntax, added negation searches (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;no:label&lt;/code&gt;), and more state queries (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;is:merged&lt;/code&gt;) as we went along.&lt;/li&gt;
  &lt;li&gt;We found ourselves doing the same simple searches over and over again, so we restored the old quick filters (like Your issues) and added a few more.&lt;/li&gt;
  &lt;li&gt;Our audit log—the history of changes to titles, assignees, labels, and milestones—went from offhand comment to part of Issues 3 in just a couple weeks.&lt;/li&gt;
  &lt;li&gt;Notifications on assignee changes went the same way. A few of us were talking about notifications one afternoon and we realized this wasn’t a thing yet. So, we coded it up and made if part of Issues 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We had a quite a few things in mind from the start, but just as many important features came naturally out of actively using the thing we were building. While that added extended the time we spent on the project, it was absolutely worth it.&lt;/p&gt;

&lt;p&gt;Separately, one thing that’s come up a lot in the last several months has been project management on GitHub. The term &lt;em&gt;project management&lt;/em&gt; is rather vague. There’s a multitude of ways in which this could manifest in GitHub, all of them independent of improving our existing issues and search infrastructure and interface. As such, it wasn’t part of this project.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I’m specifically avoiding talking too much about what we didn’t ship as there’s still a good chance we’ll ship those things. I don’t know when, and I don’t know how, but there’s still so much we can do with Issues—a fact I’m sure no one will disagree with.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;iterating&quot;&gt;Iterating&lt;/h2&gt;

&lt;p&gt;The early months of our work on Issues 3 (after those new conversations shipped) was mostly spent churning out iterations on the interface. While others focused on the underlying code, I fiddled around with the layout, aesthetics, and more. Here are a bunch of those iterations and a few brief notes regarding each.&lt;/p&gt;

&lt;h3 id=&quot;earliest-iterations&quot;&gt;Earliest iterations&lt;/h3&gt;

&lt;p&gt;As mentioned earlier, this was the opening screenshot of the issues index page, the work of &lt;a href=&quot;https://twitter.com/holman&quot;&gt;one engineer&lt;/a&gt; just going to town on what a vision for Issues could be. Turns out he was pretty spot on as well.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The design is rather inbox-y with the huge search, buttons for filtering and triaging, and the single line issues list. The reason for that was to add and streamline information to keep it in a single row for more content per page. One line per issue was a bit of a crazy goal and we’d struggle to keep to that as we iterated more.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v1-issue-show.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This screenshot is a bit of a mess as you can tell. It was from one of those interstitial states where the conversations redesign and Issues 3 were becoming confusingly intertwined. The omnipresent search at the top was one (bad) idea we tried to carry over from the issues index to individual issues.&lt;/p&gt;

&lt;p&gt;We also tried to have no sidebar on issues with this—you can see the milestone, assignee, and labels at the top of the page. Things got messy, but we were fast and flexible enough to quickly try out and discard ideas.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once that initial design was merged—it was &lt;em&gt;team shipped&lt;/em&gt;, which meant only a few GitHubbers had access to it—I started tweaking the design to explore slightly different directions. Briefly, here’s the what and why:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I minimized the search field because I still didn’t think search would or could be the primary interface for people of all ranges to interact with &lt;em&gt;first&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;I condensed the search and filter buttons into one row so you didn’t lose as much vertical real estate.&lt;/li&gt;
  &lt;li&gt;I tweaked the display of content in the issues list by collapsing labels into dots (revealing the label name on hover via tooltip), giving more weight and contrast to issue titles, and adding more content in a slightly more tabular design.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of my favorite aspects of this was the arrow to avatar for assignees. To me it read super naturally—issue titled such and such assigned to username. Later it’d cause problems for aligning and wrapping longer content.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v2-issue-show.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The design of that issues list page also mapped to the individual issue again. Things were getting even more mixed up between Issues 3 and the conversation redesign as I streamlined the gray bar and the assignee, milestone, and labels lists into it. Notifications also got moved up from the bottom of the page to a single button on the top right.&lt;/p&gt;

&lt;p&gt;The goal here was to present all your actions &lt;em&gt;above&lt;/em&gt; the rest of the page content. This way, hierarchically, it reinforced the idea that you were taking action on this page—this issue.&lt;/p&gt;

&lt;p&gt;There are some more failed ideas in here from an earlier iteration of the conversations redesign. The state indicator—the thing tells you it’s an issue or pull request, and if it’s open, closed, or merged—was like a big avatar. The opening comment was (literally) unboxed and enlarged to function as a sort of blog post style introduction to the issue or pull request. This never really ended up working out as it brought with it a few annoying differences across how we layout comments and render their Markdown content.&lt;/p&gt;

&lt;h3 id=&quot;aesthetics&quot;&gt;Aesthetics&lt;/h3&gt;

&lt;p&gt;For a long while most of my changes felt superficial. I played with button styles, orientation of search and filters, and different representations of content within the issues list.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I removed the light gray background to prevent more horizontal stripping of content, something GitHub and tons of other sites seem to struggle with. Other super subtle changes include lightening the comment bubble and count for issues without comments.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;More visual changes as I try out lighter button styles to make the page feel less full of administrative cruft. It wouldn’t work out that well for buttons originally, but those styles later resurfaced in our subnav.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I spent far too much time flipping between icon-only buttons and icon-text buttons. At this point I also started to solidify on some of the more basic aspects of the issues list that I stupidly tried out earlier on. For example, I started expanding the labels again to their natural textual state. I also restored the stateful color—green or red for open or closed—to the issue/pull request icons on the left.&lt;/p&gt;

&lt;h3 id=&quot;searching-vs-filtering&quot;&gt;Searching vs. filtering&lt;/h3&gt;

&lt;p&gt;While I struggled with it repeatedly, there was a moment when I suggested we abandon the new search field entirely.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v6.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;It was starting to annoy me that I had up to three ways to get to things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Clicking the filter buttons&lt;/li&gt;
  &lt;li&gt;Searching by hand&lt;/li&gt;
  &lt;li&gt;Hacking the address bar and using URLs only&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It felt odd that we had so many avenues to get to the same content. Eventually though, I’d come to peace with this and realize it was an advantage. Some folks love using buttons for everything, some work faster typing and using keyboard shortcuts, and some love their address bar more than life itself.&lt;/p&gt;

&lt;p&gt;Put another way, the more access points, the more we could appeal to different workflows across teams and organizations.&lt;/p&gt;

&lt;h3 id=&quot;structure&quot;&gt;Structure&lt;/h3&gt;

&lt;p&gt;Throughout our work on issues and conversations, I frequently got care-mad about the intersection of our repository navigation, page headers, section subnav, and our issues filters. I also got fed up with the single-line issues—it just wasn’t working.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v7.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So I started screwing around with more subnav-search-filters layouts and the placement of content within the issues list. The subnav moved around from the top right of the page header to the top left of the issues list and more. I think we flipped around and tried out even more ideas, but mostly these were our two “best” options.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v8.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The table-header style approach to our filters here was one of my favorite aspects as well. It felt simple, elegant, and functional and came without all the added weight that a series of buttons brings.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v9.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We realized for awhile that because we had moved the subnav—previously tabs in the old issues UI—to the page header, we suddenly had more room again. That meant making the search field ginormous again.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But something still didn’t feel right in that layout. The hierarchy felt lost again and it was rather difficult to find relationships between content and quickly find things.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v11.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At this point I panicked for nearly an entire day. I gave up everything about the new layout and tried a few ideas to see if a tabbed interface and side column would make more sense again. I don’t know if it’s just because what I tried was absolute shit or if the idea just didn’t make sense, but it felt wrong.&lt;/p&gt;

&lt;p&gt;Seeing that it felt wrong again to try the side column and tabs, I starting feeling a lot better about our new direction.&lt;/p&gt;

&lt;h3 id=&quot;additional-views&quot;&gt;Additional views&lt;/h3&gt;

&lt;p&gt;While all this work was being poured into the main issues list, we had plenty of other iterations on labels and milestones. Labels in particular are fun to compare before and after:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-labels-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The original pass was kind of fun and quirky, but not the most practical.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-labels-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We toned it down and shipped a super basic one-page list of your labels. We wanted to add more sorting and metrics, but time just didn’t allow it. Maybe next time around.&lt;/p&gt;

&lt;p&gt;We spent a decent amount of time thinking about how to educate folks about available search queries. Two earlier options include a popover when focusing on search and a set of links at the bottom of the issues list.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-protips-dark.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Compared to a set of callouts below the content:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-protips-large.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We ended up shipping a much more streamlined version of those at the bottom of the issues list. It was easier to work with, easy to ignore by more experienced users, and a fun surprise for those new to the feature.&lt;/p&gt;

&lt;h3 id=&quot;settling-down&quot;&gt;Settling down&lt;/h3&gt;

&lt;p&gt;So, I went backwards again to the table header, narrower search button, and a closer subnav for the issues, labels, and milestones links.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/08/github-issues-v12.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Instead of columns like some earlier iterations though, I switched to plain text “buttons” all right aligned above the issues list. Given that they weren’t typical button styles (gradients, box-shadows, etc), it felt lightweight and approachable.&lt;/p&gt;

&lt;p&gt;There was a bit more churn around the subnav and issues list:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added a border around the entire list of issues and the table header&lt;/li&gt;
  &lt;li&gt;Set the filters (open/closed, labels, etc) against a light gray background for contrast between chrome and content&lt;/li&gt;
  &lt;li&gt;Tweaked the subnav styles, trying out gray text links, nav pills, and then ultimately a segmented controller style nav&lt;/li&gt;
  &lt;li&gt;Search styles to clarify the proximity of the quick filters dropdown menu and new issue button&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even with those changes, this was basically the last big iteration we went through before shipping.&lt;/p&gt;

&lt;h2 id=&quot;validating-our-ideas&quot;&gt;Validating our ideas&lt;/h2&gt;

&lt;p&gt;The thing about working on a single project for so long was &lt;strong&gt;how do we know when to stop?&lt;/strong&gt; I struggled with this a bit. When you’re working for so long on something, you get tunnel vision and don’t want it to end. You keep telling yourself you’ve got time for one more tiny feature or one more UI change.&lt;/p&gt;

&lt;p&gt;One day I noticed something though. Whenever I wanted to churn through some Bootstrap issues, I was disabling staff mode and reverting to the old issues interface. As it turns out, I wasn’t able to get any real work done with the current design.&lt;/p&gt;

&lt;p&gt;So, that became the test for me. I’d know we were on to something awesome if I could binge close dozens of issues without using the old interface.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;For some reason we never really got to do dedicated user research studies on Issues 3. We had plenty of time, but it never solidified. We did have tangential feedback from related studies, our sales team, ourselves, and our peers who we teased with early iterations.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;shipping-it&quot;&gt;Shipping it&lt;/h2&gt;

&lt;p&gt;The task of actually shipping Issues 3—after all the design and development was done—is mostly a familiar process to us. There were a few unique aspects for a ship of this size, but overall it went something like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We finished off all our product work and shifted gears to the blog post, small bug fixes, etc.&lt;/li&gt;
  &lt;li&gt;Given we had rewritten and improved much of our infrastructure, we had some basic production readiness reviews with our Ops folks (far too late in the process mind you, but it was better late than never).&lt;/li&gt;
  &lt;li&gt;We dark-shipped it a couple times to more accurately simulate the changes in performance. (Dark-shipping refers to silently calling a new feature’s functionality in production alongside the existing functionality. This way, you get real metrics on how folks use the service for both versions.)&lt;/li&gt;
  &lt;li&gt;When we were ready for it to go into “genpop”, we flipped the feature flag and redeployed to our servers.&lt;/li&gt;
  &lt;li&gt;After watching the graphs in Chat for 10 minutes or so, we decided it was ready to go and merged into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;. Boom, it was shipped!&lt;/li&gt;
  &lt;li&gt;Once we shipped the code, we shipped the blog post and all our documentation updates that our support team had made. Without those last two, the whole ship is a bust as support requests become a shit show rather than what I like to call a coordinated chaos.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s greatly simplifying it, but I’m not trying to provide all the technical details. That’s way too much for this post. Suffice to say we had an amazing set of dedicated individuals and teams to help us ensure a quality ship.&lt;/p&gt;

&lt;p&gt;Our Support team is always invaluable when it comes to shipping (big) features. They triage incoming feedback, bug reports, and the like so we can more efficiently react and quickly ship follow-up tweaks. I can’t stress enough the importance of that workflow to the success of this project.&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;Issues 3 wasn’t without its problems, but we worked our asses off on it for months and the launch has been overwhelmingly successful. I’m sad I don’t have more metrics and user feedback to share, but we simply didn’t collect enough of it throughout the process. Next time, we’ll do even better.&lt;/p&gt;

&lt;p&gt;And on that note, here’s to the next :ship:!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GitHub's CSS</title>
   <link href="https://markdotto.com/2014/07/23/githubs-css/"/>
   <updated>2014-07-23T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/07/23/githubs-css</id>
   <content type="html">&lt;p&gt;I’m always interested in the development details of other products, particularly their styleguides and approach to CSS. Given my penchant for the otherwise inane CSS details, I decided to write a bit about GitHub’s CSS.&lt;/p&gt;

&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;

&lt;p&gt;Given the length, here’s a helpful table of contents.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#quick-facts&quot;&gt;Quick facts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#preprocessor&quot;&gt;Preprocessor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#architecture&quot;&gt;Architecture&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#linting&quot;&gt;Linting&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#two-bundles&quot;&gt;Two bundles&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#included-via-sprockets&quot;&gt;Included via Sprockets&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#performance&quot;&gt;Performance&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#primer&quot;&gt;Primer&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#refactoring&quot;&gt;Refactoring&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;quick-facts&quot;&gt;Quick facts&lt;/h2&gt;

&lt;p&gt;A survey of our current state of CSS shows:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The preprocessor of choice is SCSS.&lt;/li&gt;
  &lt;li&gt;We have well over 100 individual source stylesheets that we compile before serving it up in production.&lt;/li&gt;
  &lt;li&gt;That compiled CSS is served via two separate stylesheets to avoid the IE&amp;lt;10 selector limit.&lt;/li&gt;
  &lt;li&gt;Those two stylesheets weigh in at around 90kb total.&lt;/li&gt;
  &lt;li&gt;There’s no particular &lt;a href=&quot;#architecture&quot;&gt;“CSS architecture”&lt;/a&gt; in place.&lt;/li&gt;
  &lt;li&gt;Pixels are the unit of choice, although we do have some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;em&lt;/code&gt;s lying around.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Added 7/24/14:&lt;/strong&gt; We use &lt;a href=&quot;https://github.com/necolas/normalize.css/&quot;&gt;Normalize.css&lt;/a&gt; and a mix of our own reset styles.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;preprocessor&quot;&gt;Preprocessor&lt;/h2&gt;

&lt;p&gt;As mentioned above, we use SCSS. This was a choice made much before my time and I’m a-okay with it (despite Bootstrap currently being written in LESS). Our SCSS is compiled by the Rails asset pipeline with some help from Sprockets (for the time being) for including the files. Read about that a bit farther down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about LESS, or Stylus, or …?&lt;/strong&gt; I don’t think LESS was ever a choice for GitHub, but I can’t really speak to that. We probably wouldn’t switch at this point either as there is no clear benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why a preprocessor?&lt;/strong&gt; Our internal framework includes a relatively small set of variables (like font stacks and brand colors) and mixins (mostly for vendor prefixed properties) that make writing code faster and easier.&lt;/p&gt;

&lt;p&gt;We don’t currently use &lt;a href=&quot;https://github.com/ai/autoprefixer&quot;&gt;Autoprefixer&lt;/a&gt;, but we really should as it would basically negate all our existing mixins. Hopefully we’ll implement it soon.&lt;/p&gt;

&lt;p&gt;We also don’t currently use &lt;a href=&quot;https://developer.chrome.com/devtools/docs/css-preprocessors#toc-how-css-source-maps-work&quot;&gt;source maps&lt;/a&gt;, but that’ll be changing soon. (If you don’t know, source maps allow you to see in the Inspector what source SCSS file a particular set of styles are coming from rather than a compiled and minified stylesheet. They’re awesome.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Added 7/24/14:&lt;/strong&gt; Other than that, our use of the tools SCSS provides is quite limited. We use color variables, mixins, color functions, math functions, and nesting. We don’t need to iterate over classes, set global options, or anything else really. I enjoy the simplicity this affords.&lt;/p&gt;

&lt;h2 id=&quot;architecture&quot;&gt;Architecture&lt;/h2&gt;

&lt;p&gt;Common CSS architectures include BEM and OOCSS. We &lt;em&gt;lean&lt;/em&gt; towards OOCSS, but we have no holistic approach. We do tend to write all our new stuff with a nebulous but basic approach:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Aim for classes over everything else in selectors&lt;/li&gt;
  &lt;li&gt;Avoid unnecessary nesting&lt;/li&gt;
  &lt;li&gt;Use (single) dashes in class names&lt;/li&gt;
  &lt;li&gt;Keep things as short as possible without adding confusion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll write more about my preferred CSS architecture in another post. For now, the above sums up GitHub’s approach, which while not perfect, serves its purpose well enough.&lt;/p&gt;

&lt;h2 id=&quot;linting&quot;&gt;Linting&lt;/h2&gt;

&lt;p&gt;We didn’t start &lt;a href=&quot;https://github.com/causes/scss-lint&quot;&gt;linting&lt;/a&gt; our SCSS until several weeks ago. We had common enough conventions, but everyone’s style and formatting was somewhat unique. Today, every CI build includes basic SCSS linting and will fail if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You have a class in your CSS but not anywhere in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/views/&lt;/code&gt; templates.&lt;/li&gt;
  &lt;li&gt;You are using the same selector multiple times (as they should almost always be combined).&lt;/li&gt;
  &lt;li&gt;The general formatting rules (nesting limits, line breaks between rulesets, lack of space after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:&lt;/code&gt;s, etc) are broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, these few rules keep our stuff decently tidy. It doesn’t account for discrepancies in commenting styles or general architecture, but that’s the stuff teams need to address themselves with real documentation. It’s something everyone here is open to improving and iterating on.&lt;/p&gt;

&lt;h2 id=&quot;two-bundles&quot;&gt;Two bundles&lt;/h2&gt;

&lt;p&gt;GitHub.com has two CSS bundles, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github2&lt;/code&gt;. The split was added years ago to solve the problem of Internet Explorer’s &lt;a href=&quot;http://blogs.msdn.com/b/ieinternals/archive/2011/05/14/internet-explorer-stylesheet-rule-selector-import-sheet-limit-maximum.aspx&quot;&gt;4,095 selectors per file limit&lt;/a&gt;. This applies to IE9 and down, and since GitHub requires a minimum of IE9, our split bundle approach must stay.&lt;/p&gt;

&lt;p&gt;This is because, as of today, GitHub has around 7,000 selectors across those two files. How’s that compare to other sites?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bootstrap v3.2.0 has just under 1,900 selectors&lt;/li&gt;
  &lt;li&gt;Twitter has just under 8,900 selectors&lt;/li&gt;
  &lt;li&gt;NY Times has just under 2,100 selectors&lt;/li&gt;
  &lt;li&gt;SoundCloud has under 1,100 selectors (&lt;strong&gt;Edit:&lt;/strong&gt; Previously I reported this at 7,400, which is the &lt;em&gt;old&lt;/em&gt; SoundCloud)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These numbers were gathered using &lt;a href=&quot;http://cssstats.com&quot;&gt;cssstats.com&lt;/a&gt;. It’s an awesome little tool that looks at your CSS in ways most folks, including myself, usually don’t. We also have graphs for this internally at GitHub and usually use those for our own purposes.&lt;/p&gt;

&lt;h2 id=&quot;included-via-sprockets&quot;&gt;Included via Sprockets&lt;/h2&gt;

&lt;p&gt;GitHub’s CSS, and JavaScript, is bundled via Sprockets and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require&lt;/code&gt;. We maintain our two CSS bundles with separate subdirectories within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;app/assets/stylesheets&lt;/code&gt; directory. Here’s how that looks:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;c&quot;&gt;/*
 = require primer/basecoat/normalize
 = require primer/basecoat/base
 = require primer/basecoat/forms
 = require primer/basecoat/type
 = require primer/basecoat/utility
 = require_directory ./shared
 = require_directory ./_plugins
 = require_directory ./graphs
 = require primer-user-content/components/markdown
 = require primer-user-content/components/syntax-pygments
 = require primer/components/buttons
 = require primer/components/navigation
 = require primer/components/behavior
 = require primer/components/alerts
 = require primer/components/tooltips
 = require primer/components/counter
 = require primer-select-menu
 = require octicons

 = require_directory .
*/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We include our dependencies—Primer is our internal framework—and then load the entire directory’s SCSS files in whatever order Sprockets decides to include them (I believe it’s alphabetical). The ease in which we can bundle our stylesheets—by simply writing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;require_directory .&lt;/code&gt;—is awesome, but it also kind of sucks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The order in which styles get applied matters.&lt;/strong&gt; It really shouldn’t, but in every design system there are rules and a basic hierarchy of styling. With the Sprockets approach, we sometimes run into specificity problems. This happens because new files can be added to either bundle at any time. Depending on their file name, they appear in different spots in the compiled CSS.&lt;/p&gt;

&lt;p&gt;Additionally, using Sprockets means that your SCSS files don’t have immediate and automatic access to your global variables and mixins. That means you have to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@import&lt;/code&gt; them explicitly at the top of any file that references a variable or mixin.&lt;/p&gt;

&lt;p&gt;Given the repetition and occasional specificity headache, we have a pull request open to switch to explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@import&lt;/code&gt;s. The added benefit is clearer insight into our CSS and easier willy-nilly experimentation with our aforementioned bundles. The downside is having to maintain that list, but I like to think of this as an added control to the overall system.&lt;/p&gt;

&lt;h2 id=&quot;performance&quot;&gt;Performance&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Added 7/24/14:&lt;/strong&gt; Bundle sizes and selector count graphs.&lt;/p&gt;

&lt;p&gt;Internally we use tons of graphs to monitor how the site and API are doing. We also track a few interesting frontend stats. For example, here’s the &lt;strong&gt;size of our two CSS bundles for the last three months:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/07/github-bundles-sizes.png&quot; alt=&quot;GitHub bundle sizes&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Similarly, here’s the &lt;strong&gt;number of selectors over the last month&lt;/strong&gt; on our blob (or file) pages. Clearly we still have some work to do there to get those element tag selectors down.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/07/github-selector-count.png&quot; alt=&quot;GitHub selector count&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Because we regularly deploy updated CSS, and we deploy dozens of times each day, we’re constantly busting the caches on our decently large CSS files. We haven’t done much in the way of optimizing these file sizes or limiting the cache busting, but we are starting to look into that more closely. It’d be awesome to have a core bundle that hopefully changes very infrequently and secondary bundle that can be more volatile.&lt;/p&gt;

&lt;p&gt;Speaking of which, at Twitter we had (I’m unsure if they still have this) two bundles, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;more&lt;/code&gt;. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;core&lt;/code&gt; was all the styles needed to keep the &lt;em&gt;time to first tweet&lt;/em&gt; number as low as possible. Everything else was in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;more&lt;/code&gt;. Given GitHub’s love of all things fast—here, it’s not shipped until it’s fast—it’s something we plan on looking into. Currently our bundle split is arbitrary.&lt;/p&gt;

&lt;p&gt;Generally, &lt;strong&gt;selector performance isn’t something we concern ourselves with&lt;/strong&gt;. We’re aware of bad practices—over-nesting, IDs, elements, etc—but we don’t try to over optimize. The one exception has been diff pages. Due to the extensive markup required in rendering a diff, we avoid attribute selectors like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[class^=&quot;octicon&quot;]&lt;/code&gt;. When used too often, those attribute selectors can (and have) crashed browsers.&lt;/p&gt;

&lt;p&gt;For the curious, Jon Rohan, a fellow GitHub design-gineer, has &lt;a href=&quot;https://speakerdeck.com/jonrohan/githubs-css-performance&quot;&gt;a great talk about GitHub’s CSS performance&lt;/a&gt; that covers these problems.&lt;/p&gt;

&lt;h2 id=&quot;documentation&quot;&gt;Documentation&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/07/github-styleguide-buttons.png&quot; alt=&quot;GitHub styleguide&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Speaking of which, we do an okay job of this, but we’re working on making improvements. We have a &lt;a href=&quot;https://github.com/styleguide/css/&quot;&gt;publicly accessible CSS styleguide&lt;/a&gt; and all our general rules for writing CSS live there, as well as examples of most components. It’s built on &lt;a href=&quot;https://github.com/kneath/kss&quot;&gt;KSS&lt;/a&gt;, a styleguide generator of sorts, and lives right in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github/github&lt;/code&gt; code base.&lt;/p&gt;

&lt;p&gt;It’s not perfect, but it helps folks find and use things. It’s also a great way to show new folks how we do things to get them up to speed faster (like me when I joined nearly two years ago).&lt;/p&gt;

&lt;h2 id=&quot;primer&quot;&gt;Primer&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2014/07/github-primer.png&quot; alt=&quot;Primer&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I alluded to it earlier, but for folks who don’t know, Primer is our internal framework for common styles and components across our public and internal apps. It includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Normalize&lt;/li&gt;
  &lt;li&gt;Global styles for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-sizing&lt;/code&gt;, typography, links, etc&lt;/li&gt;
  &lt;li&gt;Navigation&lt;/li&gt;
  &lt;li&gt;Forms&lt;/li&gt;
  &lt;li&gt;Grid system&lt;/li&gt;
  &lt;li&gt;Markdown styles&lt;/li&gt;
  &lt;li&gt;Custom select menu&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We use it on GitHub.com, Gist, and several internal apps. As a rule of thumb, if it can or should be used in another app, we consider putting it in Primer.&lt;/p&gt;

&lt;p&gt;Most of Primer’s components are documented in our styleguide (e.g., navigation, tooltips, etc). However, we’ve recently been going to town on updating and improving Primer, so lots of things are in flux there. We’ll be updating that soon to include all the things.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And for those about to ask, I’d love to open source parts of Primer,  but there’s not much happening on that front in the near future. I’m hopeful though.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;refactoring&quot;&gt;Refactoring&lt;/h2&gt;

&lt;p&gt;We have our fair share of legacy code at GitHub, and that includes our CSS. Unlike a public open source project with strict versioning rules, we burn shit down regularly if it suites us. Finding things to remove  tends to happen one of two ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Manually finding things that look alike but actually have different HTML and CSS, then combining them.&lt;/li&gt;
  &lt;li&gt;Running a script that greps for a class in our CSS to see if it exists in our views. (We’ve recently made this part of our CI tests, so we constantly see it now.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The actual process of refactoring CSS is probably not unique to GitHub. We find shit to remove, burn it down, open a PR, ping the CSS team, and ship it as fast as we can. As to who removes code, anyone can do it. We have tons of great folks &lt;em&gt;adding&lt;/em&gt; to GitHub, but we also have just as many nerds looking at what we can &lt;em&gt;remove&lt;/em&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GitHub.com flow</title>
   <link href="https://markdotto.com/2014/05/02/some-github-flow/"/>
   <updated>2014-05-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/05/02/some-github-flow</id>
   <content type="html">&lt;p&gt;The term &lt;em&gt;GitHub flow&lt;/em&gt; refers to how one can develop software with GitHub. It’s a process that minimizes friction, enables asynchronous communication (and development), and is decently flexible. For an overview, read &lt;a href=&quot;https://guides.github.com/introduction/flow/&quot;&gt;Understanding the GitHub Flow&lt;/a&gt; on &lt;a href=&quot;https://guides.github.com&quot;&gt;GitHub Guides&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Applying the GitHub flow to development of GitHub.com The Website™ builds on that, and tends to go something like this.&lt;/p&gt;

&lt;h3 id=&quot;1-find-something-to-work-on&quot;&gt;1. Find something to work on&lt;/h3&gt;
&lt;p&gt;Issues on the &lt;strong&gt;github/github&lt;/strong&gt; repository are the easiest way to find things to do. Anyone can open them, and anyone can comment on them. User and &lt;a href=&quot;https://github.com/blog/1121-introducing-team-mentions&quot;&gt;team at mentions&lt;/a&gt; are available for pinging folks with bugs, feedback, or questions.&lt;/p&gt;

&lt;p&gt;It’s worth mentioning though that we sometimes jump right into code from a meatspace discussion or from a tweet. Twitter is the best way to find out if we have bugs or performance problems in real-time while deploying code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; Get to writing code as soon as possible.&lt;/p&gt;

&lt;h3 id=&quot;2-branching&quot;&gt;2. Branching&lt;/h3&gt;
&lt;p&gt;At GitHub, almost every new contribution happens in a branch. What’s in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; should always be stable, passing tests, and ready to deploy in an instant. When I figure out what I’m working on, I cut a branch from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; and get to work.&lt;/p&gt;

&lt;p&gt;My branch naming scheme is sometimes serious and relevant, and usually not useful in the slightest. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sidebar_hit_areas&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;today_we_celebrate_our_independence_day&lt;/code&gt; are both branch names that I’ve recently worked on. Both are long gone though.&lt;/p&gt;

&lt;p&gt;Great branches really &lt;em&gt;should&lt;/em&gt; include accurate names, but most of the time it doesn’t matter because they’re so short lived. Plus, snagging the name of a branch is as easy as copy-pasting from the top of a pull request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; Just cut a branch and write some code.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Not every change happens in a branch. Super small changes can be made right to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; should the occasion, or emergency, call for it.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-pull-requests&quot;&gt;3. Pull requests&lt;/h3&gt;
&lt;p&gt;Branches are ephemeral. &lt;strong&gt;They exist for the sole purpose of creating a pull request.&lt;/strong&gt; Pull requests are more important than branches for a number of reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Suggested changes are (justifiably so) more likely to be shipped if there’s an available pull request for it.&lt;/li&gt;
  &lt;li&gt;Branches get deleted, and thus code can be lost. Pull requests are never deleted, only closed or merged.&lt;/li&gt;
  &lt;li&gt;Pull requests, like issues, are search-able, label-able, milestone-able, and mention-able. Branches? Not so much.&lt;/li&gt;
  &lt;li&gt;Pull requests can be discussed in the open and linked to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Pull requests should be created as soon as possible.&lt;/strong&gt; You should push your code and open a pull request when:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You have changes that are completely finished and just need review before merging.&lt;/li&gt;
  &lt;li&gt;You have a bunch of things to do and need to use &lt;a href=&quot;https://github.com/blog/1375%0A-task-lists-in-gfm-issues-pulls-comments&quot;&gt;GitHub task lists&lt;/a&gt; to outline what’s left.&lt;/li&gt;
  &lt;li&gt;You have questions and have no idea how to finish a part of your intended changes without pinging coworkers.&lt;/li&gt;
  &lt;li&gt;You have an idea that you’d like to discuss and test, but might not ever intend to ship.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a side note, the GitHub.com code base has 50% more pull requests than issues:&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p&gt;For those who asked, to date, the github/github repo has ~10,000 issues and ~15,000 pull requests.&lt;/p&gt;&amp;mdash; Mark Otto (@mdo) &lt;a href=&quot;https://twitter.com/mdo/statuses/461237497087811584&quot;&gt;April 29, 2014&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; Pull requests are cheap and effective. Create them early and often.&lt;/p&gt;

&lt;h3 id=&quot;4-discuss-your-code&quot;&gt;4. Discuss your code&lt;/h3&gt;
&lt;p&gt;You can define a pull request a few different ways, but first and foremost it’s a discussion around code. Code review. The best code reviews (and thus, pull requests):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Have a limited set of changes&lt;/li&gt;
  &lt;li&gt;Specifically at mention individuals or teams&lt;/li&gt;
  &lt;li&gt;Include before and after screenshots, if dealing with visible front-end changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s no harm in creating lots of pull requests for discussion. If you’re concerned about pushing unfinished work, let people know you’re not yet ready for feedback or merging to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;. Two easy ways are to preface your pull request title with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WIP: &lt;/code&gt; or to include a row of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:construction:&lt;/code&gt; emoji in the opening comment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; Make it as easy as possible for your peers to help you ship your code.&lt;/p&gt;

&lt;h3 id=&quot;5-shipping-it&quot;&gt;5. Shipping it&lt;/h3&gt;
&lt;p&gt;When it comes to deploying or shipping your code for GitHub.com, you have a few options:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Branch deploy: deploying your branch temporarily to production in place of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Branch lab deploy: deploying your branch to a specific server, which when deployed, gives you a unique URL (e.g., &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hi_mom.branch.github.com&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Merging to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;: merge your branch via the merge form on your pull request. Your branch is merged, tests are run, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; is redeployed with your changes to production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best thing to do is use branch lab because you get a real URL you can share with folks around the office. URLs are the best way to drop a link into Campfire to invite folks to view some changes. Also, there’s basically no limit to how many branches can be deployed on branch lab.&lt;/p&gt;

&lt;p&gt;When you’re changes have shipped—meaning, they’ve been merged to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;—you delete the branch. GitHub will automatically prompt you do to so after merging to ensure your list of branches stays lean.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bottom line?&lt;/strong&gt; When you’re ready to ship, test your changes in an isolated branch lab, then merge to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;shoutout-to-hubot&quot;&gt;Shoutout to Hubot&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://hubot.github.com&quot;&gt;Hubot&lt;/a&gt; is our Campfire bot that literally does (almost) all the things. Find Google images, remember things, run tests, and most importantly, deploy code. When I’m ready to deploy code, I just pop into Campfire and tell Hubot to get to it:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/deploy github/hi_mom to branch-lab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hubot will automerge &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt; if there are new changes not in my branch yet, run tests again, and then deploy my branch. If my tests fail or haven’t yet finished running, Hubot tells me that right in Campfire.&lt;/p&gt;

&lt;hr /&gt;

&lt;h3 id=&quot;more-reading&quot;&gt;More reading&lt;/h3&gt;
&lt;p&gt;If any of this interests you, definitely check out some other articles from fellow GitHubbers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://scottchacon.com/2011/08/31/github-flow.html&quot;&gt;GitHub Flow by Scott Chacon&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://zachholman.com/posts/github-communication/&quot;&gt;A Day of Communication at GitHub by Zach Holman&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://zachholman.com/posts/how-github-works/&quot;&gt;How GitHub Works by Zach Holman&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://haacked.com/archive/2012/12/07/one-year-at-github.aspx/&quot;&gt;One Year At GitHub by Phil Haack&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://opensoul.org/2012/06/05/whats-it-like-to-work-at-github/&quot;&gt;What’s it like to work at GitHub? by Brandon Keepers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Dream on</title>
   <link href="https://markdotto.com/2014/04/07/dream-on/"/>
   <updated>2014-04-07T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/04/07/dream-on</id>
   <content type="html">&lt;iframe width=&quot;660&quot; height=&quot;371&quot; src=&quot;//www.youtube.com/embed/54BCLYNkFKg?rel=0&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;This morning I was mentioned in a brief Twitter conversation, and because Jeffrey is the best, I feel obliged to reply.&lt;/p&gt;

&lt;blockquote class=&quot;twitter-tweet&quot; lang=&quot;en&quot;&gt;&lt;p&gt;&lt;a href=&quot;https://twitter.com/brendandawes&quot;&gt;@brendandawes&lt;/a&gt; &lt;a href=&quot;https://twitter.com/elliotjaystocks&quot;&gt;@elliotjaystocks&lt;/a&gt; I&amp;#39;m interested in &lt;a href=&quot;https://twitter.com/mdo&quot;&gt;@mdo&lt;/a&gt;&amp;#39;s take—from a brilliant designer who also created the bootstrap framework.&lt;/p&gt;&amp;mdash; Jeffrey Kalmikoff (@jeffrey) &lt;a href=&quot;https://twitter.com/jeffrey/statuses/453181760881176576&quot;&gt;April 7, 2014&lt;/a&gt;&lt;/blockquote&gt;

&lt;p&gt;I encourage you to read the mentioned &lt;a href=&quot;http://www.creativebloq.com/computer-arts/stopped-dreaming-41411268&quot;&gt;post by Elliot Jay Stocks&lt;/a&gt;. In it Elliot asks the question, &lt;em&gt;Why have today’s designers stopped dreaming?&lt;/em&gt; Between the article and the tweets, there are two topics I’d like to comment on.&lt;/p&gt;

&lt;h2 id=&quot;tools&quot;&gt;Tools&lt;/h2&gt;

&lt;p&gt;First, &lt;a href=&quot;https://twitter.com/brendandawes&quot;&gt;Brendan&lt;/a&gt; blames—among other unnamed things—frameworks. Consider my interest piqued.&lt;/p&gt;

&lt;p&gt;While Elliot directs his post towards the craftsmen—those swinging the tools—Brendan throws the tools themselves under the bus. He’s not alone in that line of thinking. Lots of folks hate on today’s frameworks, design tools, and the like. Usually that dislike comes out of personal preference or limited experience. That doesn’t invalidate anyone else’s use of those tools though, and we’ll all do well to remember that.&lt;/p&gt;

&lt;p&gt;Let’s consider another “framework” for a moment—iOS. Is the most important operating system of the last decade to blame for a stagnation in app design and creativity? Some might say so, but have you seen the amazing apps that are being built on iOS? They’re fucking astounding!&lt;/p&gt;

&lt;p&gt;Are frameworks the same as a mobile operating system? No, but they serve a familiar role—abstraction of common aesthetics, behaviors, and components with a focus on documentation. As absurd as it might sound, it’s hard not to see at least some similarity between the two.&lt;/p&gt;

&lt;p&gt;Are these frameworks and other tools impervious to criticism? Definitely not. &lt;em&gt;(Have you seen the number of issues against Bootstrap? It’s over 13,000!)&lt;/em&gt; However, it’s important to acknowledge that amazing things can be done with just about any tool if you have the right mindset.&lt;/p&gt;

&lt;p&gt;Bottom line, the tools aren’t (completely) to blame.&lt;/p&gt;

&lt;h2 id=&quot;web-workers&quot;&gt;Web workers&lt;/h2&gt;

&lt;p&gt;Second, from the article:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The web right now is a beautiful place. Web design has matured as an industry and the technology now enables us to create whatever we might dream of in HTML, CSS and JavaScript. But it’s clear that laziness amongst designers has never been more rife.&lt;/p&gt;

  &lt;p&gt;Thousands and thousands of cookie-cutter sites litter the internet, each one drawing just a little too much influence from the last. The blame is not to be laid at the feet of sites that provide actual website templates, but at the feet of professional designers who are churning out ‘bespoke’ sites that might as well be templates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I dare say what we’re witnessing, and what Elliot and Brendan are referring to, is not laziness. The web design and development community is in a completely different place from when we got started.&lt;/p&gt;

&lt;p&gt;We’ve been doing this stuff for 10, 15, or more years now. Those lazy designers you’re seeing? They’re lawyers, stay-at-home dads, bored teenagers, interior decorators, anthropology majors, teachers, and more. And they all just learned HTML and CSS last Tuesday afternoon while we were all eating our burritos and playing video games at work. &lt;em&gt;(Hi, that’s me in case you didn’t realize.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today’s web is filled with millions of people who don’t make websites professionally. They make them simply because they want to and the tools are in place so that they can. That’s fucking awesome!&lt;/p&gt;

&lt;p&gt;This doesn’t account for everyone though. Are some designers lazy? Yup, and at times I’m definitely one of them. The site Elliot described? It might as well be any number of the &lt;a href=&quot;http://getbootstrap.com/getting-started#examples&quot;&gt;example templates&lt;/a&gt; that come with Bootstrap. And I’m perfectly okay with that.&lt;/p&gt;

&lt;h2 id=&quot;right-or-wrong&quot;&gt;Right or wrong&lt;/h2&gt;

&lt;p&gt;Elliot and Brendan aren’t wrong. There &lt;em&gt;are&lt;/em&gt; lazy designers and developers out there, and tools and trends can make it easier for folks to be lazy. At times, I’m one of those lazy designers. Does that make any of us right or wrong? I don’t think so. Can all of us do better? Most assuredly.&lt;/p&gt;

&lt;p&gt;Using design trends helps people. We find out what &lt;em&gt;looks&lt;/em&gt; good doesn’t always &lt;em&gt;feel&lt;/em&gt; good. We find out that some tools don’t always work for every job. We find out that performance and documentation are more important than your own visual preferences. Design trends, frameworks, and the like are, among other things, learning tools. Let’s keep that in mind.&lt;/p&gt;

&lt;h2 id=&quot;sing-with-me&quot;&gt;Sing with me&lt;/h2&gt;

&lt;p&gt;Everything I do in my work at GitHub and on Bootstrap is dedicated to folks who want to make awesome stuff on the Internet. &lt;strong&gt;My dream is to help awesome people do awesome shit.&lt;/strong&gt; Nothing else gets me more stoked out of my mind than that. I get goosebumps thinking about how much the web has changed and how we can continue to shape it just by writing code and sharing our experiences.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Designers&lt;/em&gt; didn’t stop dreaming. We just have millions of people dreaming dreams different than our own. Let’s encourage and foster that by enabling these people, and ourselves, to do more—and to do better. And of course, to dream on.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Including CSS in Jekyll</title>
   <link href="https://markdotto.com/2014/02/28/including-css-in-jekyll/"/>
   <updated>2014-02-28T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/02/28/including-css-in-jekyll</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt; is a blog aware static-site generator. It’s great for building simple pages like &lt;a href=&quot;http://mdo.github.io/code-guide&quot;&gt;Code Guide&lt;/a&gt; or blogs like this one. Lately, I’ve been a big fan of Jekyll’s include functionality.&lt;/p&gt;

&lt;p&gt;Now, most folks use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_includes&lt;/code&gt; for standard partials like a site’s header or footer. Lately though, I’ve been using them to easily include CSS dependencies for fewer page requests.&lt;/p&gt;

&lt;p&gt;Say you have three CSS files to include in your Jekyll project. Normally you’d do something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;site.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;font-awesome.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;syntax.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With Jekyll, you can turn that into one file during site generation with includes and &lt;a href=&quot;http://jekyllrb.com/docs/frontmatter/&quot;&gt;YAML front-matter&lt;/a&gt;. Here’s an &lt;a href=&quot;https://gist.github.com/mdo/9265461&quot;&gt;example Gist&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The front-matter tells Jekyll to treat this page as a buildable file rather than simply another asset to copy to the generated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_site&lt;/code&gt; folder. With that in place, add any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_includes&lt;/code&gt; you like, and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing Poole</title>
   <link href="https://markdotto.com/2014/01/02/introducing-poole/"/>
   <updated>2014-01-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2014/01/02/introducing-poole</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://getpoole.com&quot;&gt;&lt;img src=&quot;/uploads/2014/01/poole-banner.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://getpoole.com&quot;&gt;Poole&lt;/a&gt; is the Jekyll butler. It’s a fully furnished Jekyll setup, designed to be a consistent and flexible starting point for Jekyll projects. It’s available today, and I’m releasing two open source themes with it.&lt;/p&gt;

&lt;h2 id=&quot;whats-included&quot;&gt;What’s included&lt;/h2&gt;

&lt;p&gt;Out of the box, Poole is a Jekyll setup that focus on the content first and foremost.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://demo.getpoole.com&quot;&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1834359/71ae4048-73db-11e3-9a3c-df38eb170537.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It does so with a limited set of styles and a foundational feature set for any project:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Complete Jekyll setup included (layouts, config, 404, RSS feed, posts, and example page)&lt;/li&gt;
  &lt;li&gt;Mobile friendly design and development&lt;/li&gt;
  &lt;li&gt;Easily scalable text and component sizing with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rem&lt;/code&gt; units in the CSS&lt;/li&gt;
  &lt;li&gt;Support for a wide gamut of HTML elements&lt;/li&gt;
  &lt;li&gt;Related posts (time-based, because Jekyll) below each post&lt;/li&gt;
  &lt;li&gt;Syntax highlighting, courtesy Pygments (the Python-based code snippet highlighter)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;themes&quot;&gt;Themes&lt;/h2&gt;

&lt;p&gt;As part of the release of Poole, I’ve created two themes for folks. One, Hyde, has already been available for some time. The second, Lanyon, is brand new today. Each theme includes all the features of Poole, and then some.&lt;/p&gt;

&lt;h3 id=&quot;hyde-2&quot;&gt;Hyde 2&lt;/h3&gt;

&lt;p&gt;Hyde 1, my first open sourced Jekyll theme, was &lt;a href=&quot;/2013/10/14/introducing-hyde/&quot;&gt;released in October&lt;/a&gt;. Along with the launch of Poole, I’ve redesigned and recoded much of it. Today’s release represents Hyde 2.0. Overall it’s still the same theme, but with many improvements under the hood.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1831228/42af6c6a-7384-11e3-98fb-e0b923ee0468.png&quot; alt=&quot;Hyde 2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you’re wondering, Hyde 1.x is &lt;a href=&quot;https://github.com/mdo/hyde&quot;&gt;available on my GitHub account&lt;/a&gt;. However, it’s no longer being actively maintained.&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;lanyon&quot;&gt;Lanyon&lt;/h3&gt;

&lt;p&gt;The second theme, &lt;a href=&quot;https://github.com/poole/lanyon&quot;&gt;Lanyon&lt;/a&gt;, is also being launched today.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1825266/be03f014-71b0-11e3-9539-876e61530e24.png&quot; alt=&quot;Lanyon&quot; /&gt;
&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1825267/be04a914-71b0-11e3-966f-8afe9894c729.png&quot; alt=&quot;Lanyon open&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Lanyon started off as a variation on Hyde to hide the sidebar. Rather than keep the two together, I figured a brand new theme was in order. Thus, Lanyon was born. The best part is &lt;strong&gt;the toggleable sidebar is handled all via CSS&lt;/strong&gt;—no JavaScript is required.&lt;/p&gt;

&lt;h3 id=&quot;theme-options&quot;&gt;Theme options&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1825269/be05ec20-71b0-11e3-91ea-a9138ef07186.png&quot; alt=&quot;Lanyon in red&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hyde and Lanyon include auto-generated navigation lists with active link highlighting, eight optional color schemes (based on the colors of &lt;a href=&quot;http://chriskempson.github.io/base16/&quot;&gt;base16&lt;/a&gt;), and reverse layouts (sidebar on the right).&lt;/p&gt;

&lt;h2 id=&quot;documentation&quot;&gt;Documentation&lt;/h2&gt;

&lt;p&gt;Docs for Poole, Hyde, and Lanyon are available in each project’s readme.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/poole/#readme&quot;&gt;Poole docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/hyde/#readme&quot;&gt;Hyde docs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/lanyon/#readme&quot;&gt;Lanyon docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Poole docs include a basic walk-through for setting up Jekyll. Each theme’s readme focuses on only theme-specific features and none of the Jekyll setup process.&lt;/p&gt;

&lt;h2 id=&quot;nomenclature&quot;&gt;Nomenclature&lt;/h2&gt;

&lt;p&gt;If you’re not familiar with  it, &lt;em&gt;The Strange Case of Dr. Jeykll and Mr. Hyde&lt;/em&gt; tells the story of a lawyer investigating the connection of two persons, Dr. Henry Jekyll and Mr. Edward Hyde. Chief among the novel’s supporting cast is a man by the name of &lt;strong&gt;Mr. Poole, Dr. Jekyll’s loyal butler&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It seemed fitting to name the project after such a man, given all he intends to do—for myself and the rest of you. Plus, it’s a killer naming scheme.&lt;/p&gt;

&lt;h2 id=&quot;github-org&quot;&gt;GitHub org&lt;/h2&gt;

&lt;p&gt;To keep everything neatly organized, everything lives in a new GitHub organization, &lt;a href=&quot;https://github.com/poole&quot;&gt;@poole&lt;/a&gt;. It includes Poole, &lt;a href=&quot;https://github.com/poole/www&quot;&gt;the Poole homepage&lt;/a&gt;, and the two themes.&lt;/p&gt;

&lt;p&gt;It behooves me to mention that if you have a bug or feature request in any of the Poole-provided files (configs, layouts, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;poole.css&lt;/code&gt;, etc), please open issues in &lt;a href=&quot;https://github.com/poole/poole&quot;&gt;@poole/poole&lt;/a&gt;. Anything directly related to the theme (like in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hyde.css&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lanyon.css&lt;/code&gt;), should be addressed in the respective theme’s repository.&lt;/p&gt;

&lt;h2 id=&quot;downloads&quot;&gt;Downloads&lt;/h2&gt;

&lt;p&gt;Snag Poole, Hyde, or Lanyon as you need from each project’s GitHub releases page.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/poole/archive/v1.0.0.zip&quot;&gt;&lt;strong&gt;Download Poole&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/hyde/archive/v2.0.0.zip&quot;&gt;&lt;strong&gt;Download Hyde&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/poole/lanyon/archive/v1.0.0.zip&quot;&gt;&lt;strong&gt;Download Lanyon&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watch the GitHub repositories to be notified of future downloads, or &lt;a href=&quot;https://twitter.com/mdo&quot;&gt;follow me on Twitter&lt;/a&gt; for updates when they become available.&lt;/p&gt;

&lt;h2 id=&quot;whats-next&quot;&gt;What’s next?&lt;/h2&gt;

&lt;p&gt;Probably some bug fixes and small feature requests, and soon maybe another simple theme. I plan on looking through my old blog designs for ideas on what to build next. If you have specific ideas, let me know on Twitter.&lt;/p&gt;

&lt;p&gt;&amp;lt;3&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing Hyde</title>
   <link href="https://markdotto.com/2013/10/14/introducing-hyde/"/>
   <updated>2013-10-14T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/10/14/introducing-hyde</id>
   <content type="html">&lt;p&gt;Say hello to &lt;a href=&quot;http://andhyde.com&quot;&gt;Hyde&lt;/a&gt;. Hyde is an elegant, open source, mobile first theme for &lt;a href=&quot;http://jekyllrb.com&quot;&gt;Jekyll&lt;/a&gt;, the popular static site generator. It’s super simple, inspired by Medium’s structural design, and is a great starting point for just about any blog.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://andhyde.com&quot;&gt;&lt;img src=&quot;https://f.cloud.github.com/assets/98681/1330948/de10196c-353f-11e3-86d0-8e967dd95722.png&quot; alt=&quot;Hyde screenshot&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mdo/hyde/&quot;&gt;Check it out on GitHub&lt;/a&gt;, or snag a &lt;a href=&quot;https://github.com/mdo/hyde/archive/v1.0.0.zip&quot;&gt;download right away&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have bugs or feature requests? &lt;a href=&quot;https://github.com/mdo/hyde/issues/new&quot;&gt;Open an issue.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&amp;lt;3&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CSS and #noparents</title>
   <link href="https://markdotto.com/2013/10/09/css-and-noparents/"/>
   <updated>2013-10-09T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/10/09/css-and-noparents</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://twitter.com/search?q=%23noparents&quot;&gt;#noparents&lt;/a&gt; is more than an emotionally charged hashtag to express your individuality and independence as an angsty teenager. Turns out it makes a lot of sense when writing CSS, too.&lt;/p&gt;

&lt;h2 id=&quot;the-fuck&quot;&gt;The fuck?&lt;/h2&gt;

&lt;p&gt;Consider the following snippets of HTML and CSS:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;jumbotron&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text-danger&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Heading&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.jumbotron&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.text-danger&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To summarize, we have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jumbotron h1&lt;/code&gt; that should have red text with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text-danger&lt;/code&gt; utility class. The problem is, due to the specificity (a parent class preceding an open-ended tag) of the first rule, our utility class has no effect. The text will remain dark gray. Shit.&lt;/p&gt;

&lt;h2 id=&quot;classes-to-the-rescue&quot;&gt;Classes to the rescue&lt;/h2&gt;

&lt;p&gt;If we modify our approach, we nullify the problem and walk away with some additional benefits.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;jumbotron&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;jumbotron-heading text-danger&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Heading&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.jumbotron-heading&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nc&quot;&gt;.text-danger&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now, adding the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text-danger&lt;/code&gt; class will work as intended. It’s worth noting two things here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;No matter what, this relies on CSS being in the proper order, but that’s always true and out of our control.&lt;/li&gt;
  &lt;li&gt;Alternate solutions could include using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!important&lt;/code&gt; or writing overrides to these kind of specific collisions. Both options suck.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bottom line: removing the parent and using a single class as our selector is the best option, and it pays off.&lt;/p&gt;

&lt;h2 id=&quot;dem-benefits&quot;&gt;Dem benefits&lt;/h2&gt;

&lt;p&gt;So, we wrote more HTML to avoid writing even more CSS. How’s this a win and why does it matter?&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;To start, we’ve &lt;strong&gt;decreased the specificity of our selector&lt;/strong&gt;. Now, any single class appearing later in our code can take over with ease, just as it does in our updated example. This is how CSS works, and keeping your code to that standard keeps your sanity.&lt;/li&gt;
  &lt;li&gt;In selectors, &lt;strong&gt;classes perform better than elements&lt;/strong&gt;. Removing that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h1&lt;/code&gt; from our CSS rule for the heading helps the browser render the page faster. In many cases this isn’t that helpful, but for larger project (like maybe a CSS framework or web app?) it can make a world of difference.&lt;/li&gt;
  &lt;li&gt;A series of classes for each component &lt;strong&gt;promotes more flexible and durable design systems&lt;/strong&gt;. The use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jumbotron&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.jumbotron-heading&lt;/code&gt; logically groups code, more effectively scopes CSS, and promotes a consistent naming convention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’d say those are some solid wins, especially when applied across an entire project.&lt;/p&gt;

&lt;h2 id=&quot;applying-it&quot;&gt;Applying it&lt;/h2&gt;

&lt;p&gt;I’ll be the first to say Bootstrap doesn’t do this enough, and it’s to our detriment. Whenever we start work on v4, I’ll be testing this approach. There will inevitably be situations where we need to keep the parents to prevent collisions out of our control (e.g., nav components and dropdowns), but I imagine we can still improve that. We’ll get there in time as we continue to experiment.&lt;/p&gt;

&lt;p&gt;Until then kids, remember this: when it comes to CSS specificity, it’s &lt;a href=&quot;https://twitter.com/search?q=%23noparents&quot;&gt;#noparents&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Go Beyond Pixels</title>
   <link href="https://markdotto.com/2013/05/10/go-beyond-pixels/"/>
   <updated>2013-05-10T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/05/10/go-beyond-pixels</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://gobeyondpixels.com&quot; target=&quot;_blank&quot;&gt;
  &lt;img src=&quot;/uploads/2013/05/gobeyondpixels.jpg&quot; alt=&quot;Go Beyond Pixels&quot; style=&quot;&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next month I’m be heading to Newfoundland for &lt;a href=&quot;http://gobeyondpixels.com&quot;&gt;Go Beyond Pixels&lt;/a&gt;, a two day design and development event organized by &lt;a href=&quot;http://twitter.com/fourandthree&quot;&gt;Levin Mejia&lt;/a&gt;. I’ll be leading the hackathan on day one and then giving a talk on day two about the future of front-end frameworks and how they’re changing how we do design and development.&lt;/p&gt;

&lt;p&gt;I’m excited to be joining an amazing lineup and heading across the continent to hang out with new folks. Look forward to seeing some of you there!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Formatting code on GitHub</title>
   <link href="https://markdotto.com/2013/04/23/formatting-code-on-github/"/>
   <updated>2013-04-23T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/04/23/formatting-code-on-github</id>
   <content type="html">&lt;p&gt;I see a fair number of  issues, pull requests, and comments on GitHub from folks who don’t know how to highlight snippets of code. While this is a problem in it’s own right and we should solve that, I figure I’d drop some knowledge until we figure that other stuff out at GitHub.&lt;/p&gt;

&lt;h2 id=&quot;inline-code&quot;&gt;Inline code&lt;/h2&gt;

&lt;p&gt;Inline code is wrapped in backticks—the ``` character.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;This is an example of inline ```.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Unlike normal HTML, there is no need to escape angle brackets—GitHub Flavored Markdown does that for you.&lt;/p&gt;

&lt;h2 id=&quot;code-blocks&quot;&gt;Code blocks&lt;/h2&gt;

&lt;p&gt;Multiple lines of code are easily created by placing three backticks before and after a code block.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;```
.element {
  ...
}
```&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;language-specific-code-blocks&quot;&gt;Language-specific code blocks&lt;/h2&gt;

&lt;p&gt;You can optional specify a language for proper syntax highlighting on code blocks. Just add the language identifier after the first set of backticks.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;```css
.element {
  ...
}
```&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;/h2&gt;

&lt;p&gt;More of the &lt;a href=&quot;https://help.github.com/articles/github-flavored-markdown&quot;&gt;GitHub Flavored Markdown&lt;/a&gt; nuances are documented on the GitHub Help site. Check it out for information on autolinking, task lists, Emoji, and more.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The Designer-Developer spectrum</title>
   <link href="https://markdotto.com/2013/04/22/designer-developer-spectrum/"/>
   <updated>2013-04-22T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/04/22/designer-developer-spectrum</id>
   <content type="html">&lt;p&gt;I’ve noticed that there are still a few folks who firmly believe designers and developers are two separate types of Web workers. From their perspective, there is no overlap in skills, tools, hobbies, or ambitions, and as such, neither can do any part of the other’s job. That’s an awfully narrow-minded view, and is largely inaccurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Designer and developer roles are a spectrum.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can be all designer, or all developer. You can be mostly designer with some developer, or mostly developer with some designer. Hell, you can even be the golden unicorn of Web workers everywhere if you’re half-n-half (or just both?). Most of the best designers and developers I know are all over this spectrum.&lt;/p&gt;

&lt;p&gt;Designers and developers—like any other group of people—shouldn’t be pigeonholed into separate roles. Doing so is damaging to individuals, your company, and the entire industry. Quality products and cultures thrive on employing &lt;a href=&quot;/2011/04/15/fatten-up-those-ts/&quot;&gt;people with a broad set of skills&lt;/a&gt; and at least one specialization. Embrace the sliding spectrum of skills.&lt;/p&gt;

&lt;p&gt;I typically think of myself as a designer, but I spend most of my time writing code. Does that make me less of a designer? No, &lt;strong&gt;that makes me more knowledgeable about the medium I work on.&lt;/strong&gt; Any experienced worker from nearly any industry knows how paramount that can be. &lt;strong&gt;Know your craft&lt;/strong&gt;—it’s goal, medium, impact, and end product.&lt;/p&gt;

&lt;p&gt;Bottom line? &lt;strong&gt;Get talented people together that can have fun and ship awesome shit, and good things will follow.&lt;/strong&gt; Don’t worry about the labels.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Shoutout to &lt;a href=&quot;https://twitter.com/kneath&quot;&gt;@kneath&lt;/a&gt; who I believe originally brought this up at some point, and to that guy on Twitter who prompted this whole thing.&lt;/p&gt;

&lt;p&gt;&amp;lt;3&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Future Insights Live</title>
   <link href="https://markdotto.com/2013/04/03/future-insights-live/"/>
   <updated>2013-04-03T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/04/03/future-insights-live</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://futureinsightslive.com&quot; target=&quot;_blank&quot;&gt;
  &lt;img src=&quot;/uploads/2013/04/fi-live.png&quot; alt=&quot;Future Insights Live&quot; style=&quot;width: 50%; margin: 0 auto 3rem;&quot; /&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I’m super excited (and nervous!) to &lt;a href=&quot;http://www.futureinsights.com/home/learn-about-the-web-frameworks-of-tomorrow.html&quot;&gt;announce&lt;/a&gt; that I’m joining an outstanding lineup at &lt;a href=&quot;http://futureinsightslive.com&quot;&gt;Future Insights Live in Las Vegas&lt;/a&gt; this month to talk about Bootstrap. In spirit of the conference theme, the title of the talk is &lt;em&gt;Frameworks of Tomorrow&lt;/em&gt;, and while that sounds science fiction, there should be a good amount of practical know-off to be had.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s the summary of the talk:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Frameworks have long been an important part of building on the Web. Tools of all shapes and sizes have become common place within our design and development processes, and their prominence shows no sign of slowing down. In fact, we’ll continue to see more and more frameworks in the near future, but perhaps not in the same vein as those of today.&lt;/p&gt;

  &lt;p&gt;Nearly two years ago, the type of frameworks we use dramatically changed, and they’ll do the same again in the near future. We’ll take a brief look back through not only the evolution of front-end frameworks, but where they may be heading in the next couple years—and how to prepare yourself for them today.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In addition to the talk, I’ll be doing a workshop as well, &lt;em&gt;Building with Bootstrap&lt;/em&gt;, about how to best develop with and customize on top of Bootstrap. That will be announced and detailed next week.&lt;/p&gt;

&lt;p&gt;Looking forward to seeing a bunch of you nerds there!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Feedback</title>
   <link href="https://markdotto.com/2013/04/01/feedback/"/>
   <updated>2013-04-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/04/01/feedback</id>
   <content type="html">&lt;p&gt;This weekend I set up a new GitHub repo for &lt;a href=&quot;https://github.com/mdo/feedback&quot;&gt;collecting feedback&lt;/a&gt; from you fine folks. I use GitHub every day on account of working there and that whole Bootstrap thing, so it kind of makes sense. I also suck at responding to personal email, especially about the small things. Issues are just easier.&lt;/p&gt;

&lt;p&gt;Moreover, issues are public and searchable. This makes my answers infinitely more transparent and hopefully saves you and I time down the line. Email is so inefficient that way.&lt;/p&gt;

&lt;p&gt;So, ask a question, leave a comment, or derp with me. &lt;a href=&quot;https://github.com/mdo/feedback&quot;&gt;Just do it on GitHub.&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Make everything an experience</title>
   <link href="https://markdotto.com/2013/03/20/make-everything-an-experience/"/>
   <updated>2013-03-20T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/03/20/make-everything-an-experience</id>
   <content type="html">&lt;p&gt;There is no such thing as a user experience designer. &lt;strong&gt;&lt;em&gt;User experience&lt;/em&gt; as a discipline is only kind of a thing in that people generally value good experiences and we should strive to create more of those.&lt;/strong&gt; Does that deserve it’s own label or job title? Probably not.&lt;/p&gt;

&lt;p&gt;Making things into good experiences though, now &lt;em&gt;that’s&lt;/em&gt; a thing. We as designers and developers are all just trying to do awesome shit and hoping people find value in it. Good experiences are merely a side effect of creating or doing something people can appreciate. Like calling a cab and watching it drive to you via GPS on your phone. Like buying something online and it arriving the next day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Like playing music in the office restrooms&lt;/strong&gt; (as we do at GitHub).&lt;/p&gt;

&lt;p&gt;Holy crap (haha) sharing a restroom with other people can be awkward as hell. I obviously have no idea if this is the case for women, but we men are immature and easily perturbed by the restroom activities of other men. Restrooms are cold. People avoid eye contact. No one talks to each other. Every little noise echoes like it’s on a mission of ultimate embarrassment. Not really the stuff great experiences are made of (no matter what your bro tells you about his latest, &lt;em&gt;ahem&lt;/em&gt;, victory).&lt;/p&gt;

&lt;p&gt;Playing music over speakers is a great way to remove some of that anxiety. It makes people more comfortable, makes the entire process feel less like a silent and mindless ritual, and, most importantly, lessens that whole echo problem. Overall, it feels like a better experience.&lt;/p&gt;

&lt;p&gt;Except when you walk up to a urinal and &lt;a href=&quot;http://www.youtube.com/watch?v=a01QQZyl-_I&quot;&gt;Under Pressure&lt;/a&gt; starts playing.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Reintroducing Preboot</title>
   <link href="https://markdotto.com/2013/02/28/reintroducing-preboot/"/>
   <updated>2013-02-28T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/02/28/reintroducing-preboot</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://getpreboot.com&quot;&gt;&lt;img src=&quot;/uploads/2013/02/preboot-2-launch.png&quot; alt=&quot;Preboot 2&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; there was Preboot, a collection of LESS variables and mixins originally released in March 2011 under the name Bootstrap.less. Sensing the need for a larger and more comprehensive framework—and not wanting to launch with our internal name—I stole the &lt;em&gt;Bootstrap&lt;/em&gt; name from myself and put that code to better use as the groundwork for a much larger vision.  To avoid obvious naming issues, I renamed the project and essentially didn’t touch the it for two years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Today I’m stoked to &lt;a href=&quot;http://www.youtube.com/watch?v=W9zht1Oo6Wc&quot;&gt;reintroduce&lt;/a&gt; the project with &lt;a href=&quot;http://getpreboot.com&quot;&gt;Preboot 2&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Preboot 2 is essentially a backport of all the improvements done in Bootstrap to the original LESS variables and mixins I wrote, with a little extra on top. In the near future, you’ll see some of these once again shared for Bootstrap 3. But enough of that, here are the highlights:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A plethora of &lt;strong&gt;useful and customizable variables&lt;/strong&gt; including grayscale and semantic colors like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@black-50&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@brand-success&lt;/code&gt;, scaffolding settings like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@body-background&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@link-color&lt;/code&gt;, and typographic shortcuts for font stacks, sizes, headings, and more.&lt;/li&gt;
  &lt;li&gt;A &lt;strong&gt;powerful, semantic, and mobile-first grid system&lt;/strong&gt; to create your own layouts with ease with just three mixins: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.make-row()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.make-column()&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.make-column-offset()&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Several &lt;strong&gt;vendor-prefix mixins&lt;/strong&gt; to streamline writing of common CSS3 functions like transitions, gradients, and more.&lt;/li&gt;
  &lt;li&gt;Several &lt;strong&gt;utility mixins&lt;/strong&gt; for reusing common snippets of code like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.clearfix()&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text-truncate()&lt;/code&gt;, and more.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Head on over the docs and check it out yourself. &lt;a href=&quot;https://github.com/mdo/preboot/&quot;&gt;Everything is on GitHub&lt;/a&gt;, so if you have a feature request or bug to report, just &lt;a href=&quot;https://github.com/mdo/preboot/issues/new&quot;&gt;open an issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Improved Terminal hotness</title>
   <link href="https://markdotto.com/2013/01/13/improved-terminal-hotness/"/>
   <updated>2013-01-13T00:00:00+00:00</updated>
   <id>https://markdotto.com/2013/01/13/improved-terminal-hotness</id>
   <content type="html">&lt;p&gt;A few months ago (!) I wrote about &lt;a href=&quot;/2012/10/18/terminal-hotness&quot;&gt;customizing your Terminal prompt&lt;/a&gt;. It would seem I had a bug in there that caused some awful wrapping in Terminal, but fret not, there is a solution. &lt;a href=&quot;http://twitter.com/trmw&quot;&gt;Matt Wright&lt;/a&gt; was kind enough to hit me up &lt;a href=&quot;https://gist.github.com/4527673&quot;&gt;with a fix&lt;/a&gt;, so here are the new goods with instructions on how to update.&lt;/p&gt;

&lt;p&gt;As you recall, here’s what we’re going for with our new Terminal prompt:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2012/10/terminal-prompt.png&quot; alt=&quot;New Terminal prompt&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To get us there, open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt;. If you already have a modified prompt, replace the existing similar line with this new snippet. If you don’t have one yet, just add the following snippet:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PS1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\[\e[0:35m⌘\e[m \e[0:36m\w/\e[m \e[0:33m`git branch 2&amp;gt; /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\e[m\]'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Save and restart Terminal. Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Terminal hotness</title>
   <link href="https://markdotto.com/2012/10/18/terminal-hotness/"/>
   <updated>2012-10-18T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/10/18/terminal-hotness</id>
   <content type="html">&lt;p&gt;The default Terminal prompt is kind of bad—it tells me very little and doesn’t look super fly. After a bit of research, I learned how to customize colors, characters, variables, and show my git branch name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s what the default Terminal looks like:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;ComputerName:~/Directory/Path username &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Plain, and some what informative, but &lt;strong&gt;I don’t care about most of this&lt;/strong&gt;. I know who I am and what computer I’m using, so that can go away. I also don’t need a $ to identify new lines. What I &lt;em&gt;do&lt;/em&gt; need is some flavor, the path, and some git info. So I cooked up my own prompt to give me just that. Now, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2012/10/terminal-prompt.png&quot; alt=&quot;New Terminal prompt&quot; /&gt;&lt;/p&gt;

&lt;p&gt;To use this yourself, open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bash_profile&lt;/code&gt; in your favorite editor, and &lt;strong&gt;add the following snippet:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PS1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'\e[0:35m⌘\e[m \e[0:36m\w/\e[m \e[0:33m`git branch 2&amp;gt; /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\e[m'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Save your changes and restart Terminal. Voilà.&lt;/strong&gt; Breaking it down some, here’s what’s going on in this snippet, as outlined by &lt;a href=&quot;http://www.thegeekstuff.com/2008/09/bash-shell-ps1-10-examples-to-make-your-linux-prompt-like-angelina-jolie/&quot;&gt;this Geek Stuff article&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\e[&lt;/code&gt; starts a new color, while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\e[m&lt;/code&gt; ends it.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0:35&lt;/code&gt; is the color we’re setting for the ⌘ character. All declared colors take on the format of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;X:Ym&lt;/code&gt; (yes, the &lt;em&gt;m&lt;/em&gt; is required).&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\w&lt;/code&gt; is a variable for outputting the current path. Other available variables include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\h&lt;/code&gt; for hostname and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\u&lt;/code&gt; for username.&lt;/li&gt;
  &lt;li&gt;Lastly, we grep throught the list of branches and output that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Honestly, I don’t know much about the last part, but it’s a small script I picked up on with a big of Googling and has worked without a hitch so far.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Anywho, that’s it. You can easily swap out the ⌘ special character and change the colors to make it your own. Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Don't recreate the platform</title>
   <link href="https://markdotto.com/2012/10/03/dont-recreate-the-platform/"/>
   <updated>2012-10-03T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/10/03/dont-recreate-the-platform</id>
   <content type="html">&lt;p&gt;At Twitter, the Design team is broken down into a number of verticals: corporate, research, mainstream/feature, and platform. The balance of the last two, designing features and designing platforms, represents an important rule of thumb for building on the Web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don’t recreate something the platform already provides.&lt;/strong&gt; This guideline tends to manifest in two areas:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Designing features versus designing reusable components.&lt;/li&gt;
  &lt;li&gt;Developing new functionality versus utilizing existing functionality provided by the platform.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the first one, your team has to find balance in building new things within the constraints of a potentially already designed system: your product. Don’t spend time creating new variations on your grids, typography, buttons, navigation, and the like. Instead, &lt;strong&gt;spend your time innovating on top of constraints.&lt;/strong&gt; Focusing on recreating your most common components in every project only undermines your own efforts. Identify those constraints and make them work.&lt;/p&gt;

&lt;p&gt;In the second area, the issue is using what the platform gives you or spending time to recreate that existing functionality. Why recreate checkbox functionality when you can simply use checkboxes? In most cases, the former means additional markup, CSS, and JavaScript. In the latter, you get all that behavior for free simply by using native HTML. Now, this doesn’t apply to every situation: sometimes you need to &lt;em&gt;extend&lt;/em&gt; existing functionality. In that situation, it becomes an issue of return on investment, and it’s up to your team to make that call.&lt;/p&gt;

&lt;p&gt;Don’t let rules cripple the innovation or progress of your team, but try to design within meaningful constraints. Great design is always mindful of striking out on your own and respecting the platform you’re developing on.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GitHub bound!</title>
   <link href="https://markdotto.com/2012/09/30/github-bound/"/>
   <updated>2012-09-30T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/09/30/github-bound</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/uploads/2012/09/octocat-trekkie.png&quot; alt=&quot;Trekkie Octocat&quot; /&gt;&lt;/p&gt;

&lt;p&gt;While I announced it on Twitter and Hacker News, I want to top it off with a quick blog post: &lt;strong&gt;I’m joining GitHub this October!&lt;/strong&gt; I’ll be a designer on the &lt;a href=&quot;https://enterprise.github.com/&quot;&gt;Enterprise&lt;/a&gt; team, working with a small group of awesome engineers to make GitHub better, faster, and &lt;a href=&quot;http://www.youtube.com/watch?v=gAjR4_CbPpQ&quot;&gt;stronger&lt;/a&gt; for teams everywhere.&lt;/p&gt;

&lt;p&gt;I’ve been a user of GitHub for years, having watched repos to track interesting projects. It was always useful, but I it wasn’t until we released Bootstrap in August 2011 that I really saw its potential. Since then, I’ve used it just about every single day to manage thousands of issues, push code, and more. Beyond the product itself, it’s the people that most attracted me to GitHub. The company is almost entirely developers and designers, and that’s a powerful and inspiring combination.&lt;/p&gt;

&lt;p&gt;Lastly, I want to once again reiterate that &lt;a href=&quot;https://twitter.com/fat&quot;&gt;@fat&lt;/a&gt; and I will continue to work on Bootstrap with a 2.1.2 release dropping in the coming weeks. Beyond that, we’re working with &lt;a href=&quot;https://twitter.com/cra&quot;&gt;@cra&lt;/a&gt; at Twitter to move Bootstrap into it’s own organization on GitHub so we can build out a larger team of dedicated contributors to make Bootstrap even better.&lt;/p&gt;

&lt;p&gt;I’m stoked to be joining GitHub and couldn’t be more excited about the future of Bootstrap. Thanks everyone who have made both so great.&lt;/p&gt;

&lt;p&gt;&amp;lt;3&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Take action</title>
   <link href="https://markdotto.com/2012/08/17/take-action/"/>
   <updated>2012-08-17T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/08/17/take-action</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://byfat.xxx/burn-your-idols&quot;&gt;Today’s guest post&lt;/a&gt; on &lt;a href=&quot;http://twitter.com/fat&quot;&gt;@fat&lt;/a&gt;’s blog by &lt;a href=&quot;http://twitter.com/divya&quot;&gt;@divya&lt;/a&gt; is a pertinent one that reflects on the community we work and play in. Her point is best articulated with this line:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;By idolising people, I gave up on my opportunity to change the world, learn something exhilaratingly new, call out the wrongs done, and contribute to right some of the wrongs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this one, referring to her own successes:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;None of these required any particular skill or talent, they are merely results of taking an action.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;http://rd.io/x/QFoJK29Upg&quot;&gt;Keep pushing.&lt;/a&gt; Don’t simply do what the rest of us do—do it differently, do it better, do it faster. Take a stance and have an opinion. Don’t be afraid to be wrong. In fact, you should &lt;em&gt;expect&lt;/em&gt; to be proved wrong. We learn the most when we take a chance on something and discover our assumptions were incorrect. Taking risks with our own ideas is how we learn to be stay both humble &lt;em&gt;and&lt;/em&gt; ambitious. It’s a delicate balance, but one of the most important—you have little to lose and so very much to gain just by being yourself.&lt;/p&gt;

&lt;p&gt;So, burn your idols, but most importantly, take action.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>GitHub all the things</title>
   <link href="https://markdotto.com/2012/08/09/github-all-the-things/"/>
   <updated>2012-08-09T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/08/09/github-all-the-things</id>
   <content type="html">&lt;p&gt;I’ve GitHubbed all the things today—more on that shortly—and while I was doing that, I broke the Internet for a decent amount of folks. I apologize for that and will do my best to ensure it won’t happen again. Here’s some background and an explanation for what happened.&lt;/p&gt;

&lt;h2 id=&quot;githubbing&quot;&gt;GitHubbing&lt;/h2&gt;

&lt;p&gt;Previously, my blog used WordPress and was hosted on Media Temple. Everything was version controlled with git already, making things relatively straightforward in case something went wrong, but it was still a pain. Hosting and updating my blog was tedious, having to install WordPress and it’s plugins, pushing code, FTPing in case something broke, and SSHing into my server to pull it down. Not so &lt;a href=&quot;/2012/07/11/simpler&quot;&gt;simple&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now it’s all GitHub, all the time.&lt;/strong&gt; This blog is still written in Markdown, but it’s powered by &lt;a href=&quot;http://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; and deployed &lt;a href=&quot;https://help.github.com/categories/20/articles&quot;&gt;using GitHub Pages&lt;/a&gt;. It happens in one fell swoop: just push. Super simple.&lt;/p&gt;

&lt;p&gt;Fellow Twit and broheim &lt;a href=&quot;http://twitter.com/dhg&quot;&gt;Dave Gamache&lt;/a&gt; also has a &lt;a href=&quot;http://davegamache.com/hosted-on-github/&quot;&gt;nice write-up on using GitHub Pages&lt;/a&gt;, so be sure to check that out. His blog setup was the inspiration for this entire endeavor and his support in the process was invaluable.&lt;/p&gt;

&lt;h2 id=&quot;i-broke-the-internet&quot;&gt;I broke the Internet&lt;/h2&gt;

&lt;p&gt;No joke, I messed some stuff up, and again, I apologize for that. Here’s what happened as succinctly and accurately as I can recall.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Early Wednesday morning I created a new &lt;a href=&quot;https://help.github.com/articles/user-organization-and-project-pages&quot;&gt;GitHub user page&lt;/a&gt; using the repo name &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdotto.github.com&lt;/code&gt;. At this point, all is well.&lt;/li&gt;
  &lt;li&gt;To make the new GitHub page point to my domain, I added a &lt;a href=&quot;https://help.github.com/articles/setting-up-a-custom-domain-with-pages&quot;&gt;custom domain&lt;/a&gt;. At this point, the shit starts hitting the fan: all my projects are now being pointed to markdotto.com.&lt;/li&gt;
  &lt;li&gt;As the DNS propagated, the URLs of my &lt;a href=&quot;http://ghbtns.com&quot;&gt;Unofficial GitHub Buttons&lt;/a&gt; began to change from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdotto.github.com/github-buttons&lt;/code&gt; to redirect to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdotto.com/github-buttons&lt;/code&gt;, resulting in security errors as the URLs of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; were no longer resolving. To make matters worse, once I noticed the problem and attempted to resolve, some of those URLs were still being cached.&lt;/li&gt;
  &lt;li&gt;At this point I figured out the problem: despite what the GitHub Pages docs say, &lt;strong&gt;you cannot use a custom domain on your user page without it affecting your project pages&lt;/strong&gt;.&lt;/li&gt;
  &lt;li&gt;To fix all these issues, I have nuked the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdotto.github.com&lt;/code&gt; repo and created a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;markdotto.github.com/mdo&lt;/code&gt; one to point to my personal domain. Alongside that, I bought a new domain and pointed the GitHub Buttons project to that using the same technique.&lt;/li&gt;
  &lt;li&gt;This change requires everyone using the buttons to update the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;src&lt;/code&gt; on their &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; to begin with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://ghbtns.com/github-btn.html?&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that brings us to now. Caching might still present security warnings for folks, but there isn’t much I can do about that at this point. From here on out, the core issues should be resolved.&lt;/p&gt;

&lt;h2 id=&quot;moving-forward&quot;&gt;Moving forward&lt;/h2&gt;

&lt;p&gt;Despite all the hiccups on the GitHub buttons, I did manage to roll out some updates for it tonight:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Retina icons for in the buttons&lt;/li&gt;
  &lt;li&gt;Changed “Watch” button’s text to “Star” (the type is still going to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;watch&lt;/code&gt; in the code until the API changes)&lt;/li&gt;
  &lt;li&gt;Added caret to the count like on GitHub.com&lt;/li&gt;
  &lt;li&gt;Overhauled CSS better match GitHub.com buttons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check it out at &lt;a href=&quot;http://ghbtns.com&quot;&gt;http://ghbtns.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I also pushed some changes to this blog and, after some miscellaneous cleanup on the code, will be propgating them to the &lt;a href=&quot;http://blog.getbootstrap.com&quot;&gt;Bootstrap blog&lt;/a&gt; shortly since it uses the same template. New to the blog are larger tweet buttons on articles (better for mobile), related posts on each post page, and a &lt;a href=&quot;/&quot;&gt;streamlined homepage&lt;/a&gt; for faster loading. More changes to come, so stay tuned.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Simpler</title>
   <link href="https://markdotto.com/2012/07/11/simpler/"/>
   <updated>2012-07-11T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/07/11/simpler</id>
   <content type="html">&lt;p&gt;Writing about simplicity is difficult. It’s tough to not sound egregiously grandiose or obnoxiously obvious, but sometimes we all need that. And right now, I need that, if only for my own sanity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything needs to be fucking simpler.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This manifests itself in a number of ways, none more apparent to me than in interface and product design. Consider how many successful products you use that focus on one amazing &lt;em&gt;thing&lt;/em&gt;: Byword, Dropbox, Rdio, Uber. All these products and their interfaces are the result of paring down an idea to only the most essential. People love this stuff.&lt;/p&gt;

&lt;p&gt;We want—need?—fewer, higher quality &lt;em&gt;things&lt;/em&gt; in our lives. We crave simpler at every turn. As designers we can provide that.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Comma-separated values in LESS mixins</title>
   <link href="https://markdotto.com/2012/04/05/comma-separated-values-in-less-mixins/"/>
   <updated>2012-04-05T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/04/05/comma-separated-values-in-less-mixins</id>
   <content type="html">&lt;p&gt;With some CSS3 properties, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-shadow&lt;/code&gt;, it is possible to have a comma-separated list of values for multiple shadows like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#eee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f5f5f5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works well with regular ol’ CSS, but with CSS3 support being what it is, we sometimes want to use &lt;a href=&quot;http://lesscss.org&quot;&gt;LESS&lt;/a&gt; mixins for properties like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;. Given we need various vendor prefixes in our mixin, our example changes to this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.box-shadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;-webkit-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;nl&quot;&gt;-moz-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.box-shadow(0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#eee,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#f5f5f5);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However, when you use LESS with this approach, the compiler will choke on the unexpected comma between those two shadows. With recent versions of LESS, one might think &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@arguments&lt;/code&gt; is the solution, but that only gets you past the compiling problem. You’ll still end up with a final output that strips that ever important comma between the two shadows. While the most straightforward approach doesn’t work, there are at least two ways of making comma-separated values work in LESS.&lt;/p&gt;

&lt;p&gt;The first is to &lt;strong&gt;use a local throw-away variable&lt;/strong&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.box-shadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;-webkit-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;nl&quot;&gt;-moz-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#eee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f5f5f5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.box-shadow(@shadow);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This works because we’re declaring a value that’s a literal string because it’s a variable and the mixin respects the entire contents of that variable, including the comma. We currently use this method across Bootstrap for it’s simplicity and because we didn’t know of any other options at the time until we discovered this second method.&lt;/p&gt;

&lt;p&gt;Your other option is to &lt;strong&gt;escape the value when you call the mixin:&lt;/strong&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.box-shadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;@shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;-webkit-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
     &lt;span class=&quot;nl&quot;&gt;-moz-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
          &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.box-shadow(~&quot;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#eee,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#f5f5f5&quot;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This effectively does the same thing as the local variable: it ensures the value passed to the mixin is a string and not a list of options compressed into a single value. The syntax is a still fairly clear,  but also more succinct. One potential downside to note is that this method doesn’t enable you to place line-breaks and spaces between values to stack them in your code for improved readability, meaning this wouldn’t compile:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.box-shadow(~&quot;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#eee,&lt;/span&gt;
                  &lt;span class=&quot;err&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;#f5f5f5&quot;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If that’s your style, you can accomplish this with the local variable method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.element&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;py&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#eee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
             &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#f5f5f5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;.box-shadow(@shadow);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All in all, it depends on your own style and conventions. Whatever method you opt for, I do recommend being consistent with it throughout entire projects.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;It’s worth noting that in the next version of Bootstrap, we’ll be using the second method (escaping when we call the mixin). It’s less code to write and those familiar with LESS shouldn’t be caught off guard by the escaping.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Learnings from open-sourcing Bootstrap</title>
   <link href="https://markdotto.com/2012/04/02/learnings-from-open-sourcing-bootstrap/"/>
   <updated>2012-04-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/04/02/learnings-from-open-sourcing-bootstrap</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; wasn’t my first open-source project, but it’s definitely the largest and most successful, largely thanks to &lt;a href=&quot;http://twitter.com/fat&quot;&gt;Jacob&lt;/a&gt; and &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;the community&lt;/a&gt; of course. Since open-sourcing Bootstrap seven months ago, I’ve realized a few things about open-source that I’d like share with you all.&lt;/p&gt;

&lt;h2 id=&quot;communication-is-paramount&quot;&gt;Communication is paramount&lt;/h2&gt;

&lt;p&gt;No matter the success of an open-source project, folks using your hard work begin to depend on you and what you’re doing. Communication becomes more important as the age and use of the project increases. When’s the next release, and what will it include? Does the license allow for X, Y, or Z? What about support for third party plugins like A or B? Questions like this are bound to arise, so you have to be proactive to fight the brunt of it and keep your sanity.&lt;/p&gt;

&lt;p&gt;To do that in Bootstrap, we use our GitHub wiki to share a &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/Roadmap&quot;&gt;roadmap&lt;/a&gt;, &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/License&quot;&gt;license info&lt;/a&gt;, a &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/Changelog&quot;&gt;changelog&lt;/a&gt;, and even &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/Contributing-to-Bootstrap&quot;&gt;contribution standards&lt;/a&gt;. We also use our &lt;a href=&quot;http://twitter.com/twbootstrap&quot;&gt;Twitter account&lt;/a&gt; and &lt;a href=&quot;http://blog.getbootstrap.com&quot;&gt;new blog&lt;/a&gt; to post about changes and releases.&lt;/p&gt;

&lt;h2 id=&quot;people-can-be-jerks&quot;&gt;People can be jerks&lt;/h2&gt;

&lt;p&gt;Let’s get this one out of the way, because it doesn’t happen often, but when it does, it sucks in a big way. Just like in real life, some folks can be jerks online. This can be from lack of context on either person’s end, assuming someone’s an idiot, or simply being too aggressive. It sucks, but it can happen. When it does, keep a level head and get past it so you can help all the other awesome folks out there.&lt;/p&gt;

&lt;h2 id=&quot;people-can-be-fucking-awesome&quot;&gt;People can be fucking awesome&lt;/h2&gt;

&lt;p&gt;Speaking of awesome, sometimes people can just be fucking awesome. My own personal credo is to “Help awesome people do awesome shit” and I stand by that through and through. To date, Bootstrap is the best way I can help talented folks do their work, and so far it’s been a blast. There are plenty of smart, diligent, and hardworking people out there who just want to help you out or learn from you. Embrace it, learn from it, and pass it on.&lt;/p&gt;

&lt;h2 id=&quot;getting-complete-context-on-issues-is-hard&quot;&gt;Getting complete context on issues is hard&lt;/h2&gt;

&lt;p&gt;Just like bug reports in a typical web project, getting the complete picture around an issue submitted on GitHub can be difficult. Inability to reproduce a particular bug, difficulty in communicating across languages, dealing with opposite levels of experience, working with different versions of the same codebase, and more are all cases that you might come across on an open-source project.&lt;/p&gt;

&lt;p&gt;Figure out a system that works well for you (in many cases, we require a live demo or &lt;a href=&quot;http://jsfiddle.net&quot;&gt;jsfiddle&lt;/a&gt;) and communicate that to your followers. Stick to it and know that sometimes it just takes a bit more time and patience.&lt;/p&gt;

&lt;h2 id=&quot;its-all-worth-it&quot;&gt;It’s all worth it&lt;/h2&gt;

&lt;p&gt;I hope you come away knowing the positive outweighs the negative in this post because when it comes right down to it, open-sourcing Bootstrap was one of the best things to happen to me personally and professionally. I’ve been able to help thousands of people do their work better and faster—all while helping them learn a bit more as they go. I’ve gotten to work with a lot of awesome people, had a blast doing it, and learned a great deal. Bootstrap has been worth every second I’ve put into it and I hope to keep it up for a long time to come.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Open-source is awesome, sometimes work is hard, &lt;a href=&quot;http://www.youtube.com/watch?v=J7532GXPnO8&quot;&gt;be excellent to each other&lt;/a&gt;, do what you love, fuck yeah.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootstrap 2.0.2 released</title>
   <link href="https://markdotto.com/2012/03/12/bootstrap-2-0-2-released/"/>
   <updated>2012-03-12T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/03/12/bootstrap-2-0-2-released</id>
   <content type="html">&lt;p&gt;A new version of Bootstrap is out today with a ton of bug fixes (over 100 closed issues), documentation improvements, and a few new features. Here’s a curated list with some details where appropriate. Download the latest from the &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before we begin, I want to note that &lt;strong&gt;you’ll have to upgrade to the LESS 1.3&lt;/strong&gt; to compile 2.0.2. For those using LESS.js, &lt;a href=&quot;http://lesscss.org&quot;&gt;download the latest&lt;/a&gt;. For those using LESS via npm, run this in your Terminal to update:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;npm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;less &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And you should be good to go. Not downloading the latest or running the update means you’ll see LESS spit out some nasty errors and it won’t compile.&lt;/p&gt;

&lt;p&gt;Now, let’s check out what’s new.&lt;/p&gt;

&lt;h2 id=&quot;documentation-updates&quot;&gt;Documentation updates&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;All docs pages now have distinct titles, such as &lt;em&gt;Scaffolding · Twitter Bootstrap&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;Updated the Apple touch icons (now black on black instead of the blue grid) and fixed the links to them in the docs.&lt;/li&gt;
  &lt;li&gt;Added new global styles docs section to the Scaffolding page.
    &lt;ul&gt;
      &lt;li&gt;Required use of HTML5 doctype&lt;/li&gt;
      &lt;li&gt;Overview of global typographic and links details&lt;/li&gt;
      &lt;li&gt;Mention of our embedded CSS reset via &lt;a href=&quot;http://necolas.github.com/normalize.css/&quot;&gt;Normalize.css&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Added version number to the download button on the docs homepage.&lt;/li&gt;
  &lt;li&gt;Updated progress bars section to simplify how the classes stack and more clearly indicate the available optional classes and styles.&lt;/li&gt;
  &lt;li&gt;Added a new example, &lt;a href=&quot;http://soundready.fm&quot;&gt;SoundReady.fm&lt;/a&gt;, to the homepage&lt;/li&gt;
  &lt;li&gt;Added various sizes to the docs for button groups&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;resolved-bugs&quot;&gt;Resolved bugs&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Removed all IE7 hacks and floats from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.input-prepend&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.input-append&lt;/code&gt;, however, this requires you to &lt;strong&gt;ensure there is no whitespace in your code&lt;/strong&gt; between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.add-on&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;In &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.input-prepend&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.input-append&lt;/code&gt;, added ability to use add-ons on both sides when you chain the selectors.&lt;/li&gt;
  &lt;li&gt;Updated lingering &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn-dark&lt;/code&gt; reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn-inverse&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Fixed issue with content being cut off in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.tab-content&lt;/code&gt; for tabbable sections.&lt;/li&gt;
  &lt;li&gt;Updated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.navbar .container&lt;/code&gt; to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;width: auto;&lt;/code&gt; to start and then reset the fixed widths via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;#gridSystem&lt;/code&gt; mixin (it’s a little dirty, but required to avoid adding another class).&lt;/li&gt;
  &lt;li&gt;Modal footer buttons are now aligned by their parent via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-align: right;&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;float: right&lt;/code&gt; on the button level. This was changed to allow the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pull-left&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pull-right&lt;/code&gt; to align buttons easily. Double check your button order with this change!&lt;/li&gt;
  &lt;li&gt;Fixed problem where default striped progress bar was green instead of blue.&lt;/li&gt;
  &lt;li&gt;Fixed CSS selector used for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;textarea&lt;/code&gt; grid sizes to properly apply the CSS (was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input &amp;gt; .span*&lt;/code&gt; and now is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input.span*&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;new-features&quot;&gt;New features&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Horizontal dividers support added to nav lists&lt;/li&gt;
  &lt;li&gt;Added basic version of badges&lt;/li&gt;
  &lt;li&gt;Added visible/hidden classes for devices&lt;/li&gt;
  &lt;li&gt;Added support for buttons in input-prepend/append component&lt;/li&gt;
  &lt;li&gt;Added .navbar-fixed-bottom support&lt;/li&gt;
  &lt;li&gt;Added .dropup support for dropdown menus to pop them upward instead of downward (this is automatically done for the newly added fixed bottom navbar).&lt;/li&gt;
  &lt;li&gt;Added mixin for &lt;a href=&quot;http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/&quot;&gt;new image replacement technique&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Added pause on hover for the carousel&lt;/li&gt;
  &lt;li&gt;Added tons of new variables for typography, buttons, forms, dropdowns, navbar, and more for the LESS pros out there. These variables have also been reflected on the Customize page.&lt;/li&gt;
  &lt;li&gt;Added new horizontal description list variation&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.disabled&lt;/code&gt; class support to the pager component (also added a mention of this to the docs)&lt;/li&gt;
  &lt;li&gt;Added &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.well-large&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.well-small&lt;/code&gt; classes for extending the well component&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;responsive-changes&quot;&gt;Responsive changes&lt;/h2&gt;

&lt;p&gt;While not a bug fix or a docs update, I wanted to specially call out this responsive CSS change. We have moved the padding from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.container&lt;/code&gt; within the &amp;lt;767px layout to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;body&lt;/code&gt;. This ensures a bit more control over containers, rows, and more when setting background colors and such.&lt;/p&gt;

&lt;h2 id=&quot;new-grid-mixins&quot;&gt;New grid mixins&lt;/h2&gt;

&lt;p&gt;Last, but not least, &lt;a href=&quot;http://twitter.com/fat&quot;&gt;Jacob&lt;/a&gt; has rewritten the grid system mixins to utilize some new features in LESS 1.3. Nothing changes for the compiled CSS, but the LESS we use to generate that code is more succinct and can now fully utilize any number of grid columns when you customize.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;For a full issue-by-issue rundown of the release, check out the now closed &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?sort=created&amp;amp;direction=desc&amp;amp;state=closed&amp;amp;page=1&amp;amp;milestone=9&quot;&gt;2.0.2 milestone on GitHub&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Stop the cascade</title>
   <link href="https://markdotto.com/2012/03/02/stop-the-cascade/"/>
   <updated>2012-03-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/03/02/stop-the-cascade</id>
   <content type="html">&lt;p&gt;Cascading styles is at the core of CSS—hell, it’s in  the name—but experience has shown that building systems with too many &lt;em&gt;cascading styles&lt;/em&gt; can be detrimental. Some times it’s completely necessary to just &lt;strong&gt;stop the cascade&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let’s take the modal of &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap&lt;/a&gt; as an example.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;modal&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;modal-header&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Modal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;modal-body&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Modal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;subheader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Content&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;modal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;like&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;additional&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;forms&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;goes&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;here&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;modal-footer&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&quot;btn&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Done&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Notice how we namespace classes at key levels—each class name begins with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modal-&lt;/code&gt;as a prefix. &lt;a href=&quot;http://www.markdotto.com/2012/02/16/scope-css-classes-with-prefixes/&quot;&gt;Class name prefixing&lt;/a&gt; makes our code more durable and easier to maintain, but it also better enables us to scope styles to only the relevant elements.&lt;/p&gt;

&lt;p&gt;Consider this snippet of CSS used to style the modal heading:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.modal&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By using this generic selector, we inadvertently change the styles of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.modal-body&lt;/code&gt;. We’ve introduced an instance of cascading styles—any &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; throughout the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.modal&lt;/code&gt; will be center aligned. Therefore, if we wanted the other instances of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; to be left-aligned, we’d have to override our brand new styles with something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.modal&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;.modal-body&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It’s worth noting that this example isn’t without its flaws, but that’s the point. With a little more time and thought, one can easily avoid this problem, avoiding extra lines of code and more complications in the overall system. Had we done things differently and altered our selector, our CSS might look like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.modal-header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;center&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By limiting the scope of a selector, we reduce the likelihood that we need additional code down the line by strengthening each component and limiting the effects of their styles. If done right, we can create an entire system of independent and durable, yet still flexible, components. It’s a promising approach I think, but one not to employ with an iron first.&lt;/p&gt;

&lt;p&gt;Some CSS should be allowed to cascade. Base typography, links, and the such are prime examples of something not to redeclare over and over again. This would only serve to weigh down a project and make it even more unmanageable. Instead, the goal as always is to strike a balance.&lt;/p&gt;

&lt;p&gt;Find ways to isolate components and make them more durable by limiting the scope of their CSS. You’ll discover that components can be more easily rearranged without causing adverse effects and the amount of code necessary will likely decrease.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Designing dropdowns in Bootstrap</title>
   <link href="https://markdotto.com/2012/02/27/bootstrap-explained-dropdowns/"/>
   <updated>2012-02-27T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/02/27/bootstrap-explained-dropdowns</id>
   <content type="html">&lt;p&gt;A recent &lt;a href=&quot;http://stackoverflow.com/questions/9433285/what-was-the-thinking-behind-the-implementation-of-the-dropdown-menu-in-twitter&quot;&gt;question on Stack Overflow regarding Bootstrap’s dropdown menus&lt;/a&gt; got me thinking I should do a few posts on some of our design decisions. Folks seem curious about certain aesthetics and behavior, and I’d love to shed some light if I can. Beyond explaining existing decisions, I hope these posts can help guide future updates to the docs as well.&lt;/p&gt;

&lt;p&gt;To start, &lt;strong&gt;let’s talk dropdowns&lt;/strong&gt;.&lt;/p&gt;

&lt;h2 id=&quot;appearance&quot;&gt;Appearance&lt;/h2&gt;

&lt;p&gt;Before &lt;a href=&quot;http://getbootstrap.com&quot;&gt;Bootstrap 2&lt;/a&gt; launched, our dropdowns were confined to the topbar (now the navbar) and were thus styled to be white text on black background. This fit with what we do on Twitter.com and helped the topbar feel more complete with the dropdowns as a natural extension of that style. However, we knew we wanted dropdowns to work in a number of components, so we flipped the color scheme back to black on white.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2012/02/bootstrap-dropdowns.png&quot; alt=&quot;Dropdowns in Bootstrap&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This resulted in improved contrast for the text (especially for typeahead) and made dropdowns work much better for buttons and the like. This gave us a standardized design and cleared up a lot of CSS had we chosen to keep the previous inverted colors. Simpler appearance, simpler codebase.&lt;/p&gt;

&lt;h2 id=&quot;behavior&quot;&gt;Behavior&lt;/h2&gt;

&lt;p&gt;There has always been contention between hover and click events in interaction design. In general I am against using hover as a trigger because things can get messy quickly. The best (worst?) example of this may have been hovercards on Twitter.com from a couple years back. They were great in terms of their content and utility, but not so great in the fact that they seemed to fire without the user intending them to. Inevitably we dropped them and now have a mini profile modal with the latest redesign.&lt;/p&gt;

&lt;p&gt;In Bootstrap, we use a mix of both hover and click though–hover for tooltips and popovers, clicks for dropdowns and more. What it really boils down to is &lt;strong&gt;user intent&lt;/strong&gt;. The purpose of a hover state is to &lt;em&gt;indicate&lt;/em&gt; something is clickable (underlined text) or to provide some quick information (full URL in a tooltip). The purpose of a click is to actually &lt;em&gt;do&lt;/em&gt; something, to take an explicit action. Opening a dropdown is an explicit action and should only happen on click.&lt;/p&gt;

&lt;h2 id=&quot;additional-notes&quot;&gt;Additional notes&lt;/h2&gt;

&lt;p&gt;It behooves me to mention a few other quick thoughts on our dropdowns:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The aesthetic was derived from menus OS X. They’re super simple, elegant, and scalable.&lt;/li&gt;
  &lt;li&gt;Prior to open sourcing Bootstrap, the dropdowns were actually fired on hover. We changed this because as soon as your cursor leaves a dropdown, it disappears.&lt;/li&gt;
  &lt;li&gt;The caret in a dropdown link is the equivalent of underlining a link: it provides some affordance for what will happen when you click this element. Don’t mistake that for providing enough information to pop the dropdown on hover though.&lt;/li&gt;
  &lt;li&gt;Because we use a click to trigger the dropdown in most implementations, there is no option for a parent link (one of the primary complaints in that Stack Overflow article). Pointing back to OS X and other toolbars, I don’t see this as a huge issue as it promotes our advocacy of using clicks to carry out an action instead of hovers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s it—dropdowns in Bootstrap explained. Stay tuned for more posts like this in the future. If you’d like me to elaborate on another particular feature of Bootstrap, please hit me up &lt;a href=&quot;http://twitter.com/mdo&quot;&gt;on Twitter&lt;/a&gt; or &lt;a href=&quot;mailto:hi@markdotto.com&quot;&gt;send me an email&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootstrap 2.0.1 released</title>
   <link href="https://markdotto.com/2012/02/17/bootstrap-2-0-1-released/"/>
   <updated>2012-02-17T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/02/17/bootstrap-2-0-1-released</id>
   <content type="html">&lt;p&gt;After a few weeks of hardcore bugfixing, Jacob and I are happy to finally push out a fairly stable patch to &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap 2&lt;/a&gt; that resolves a bunch of issues. &lt;strong&gt;Here are the highlights on what’s new:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Previously the docs called for use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.control-label&lt;/code&gt; in the examples, but the CSS didn’t make clear use of it. This class is required for horizontal forms and has been reflected in the CSS.&lt;/li&gt;
  &lt;li&gt;We’ve tried our best to improve rendering of buttons and icons across all browsers. Some issues remain; Firefox throws an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!important&lt;/code&gt;on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line-height&lt;/code&gt; for inputs, so that’s the big one.&lt;/li&gt;
  &lt;li&gt;We refined the label component style to move away from uppercase.&lt;/li&gt;
  &lt;li&gt;Added the black button option, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn-inverse&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Added a mini button class, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn-mini&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;We had to re-add the protocol, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http:&lt;/code&gt; to the HTML5 schim because IE7-8 wouldn’t recognize it, dropping some HTML5 support for those browsers and introducing major performance issues.&lt;/li&gt;
  &lt;li&gt;Resolved some issues with responsive layouts where media queries would overlap at 768px and 980px.&lt;/li&gt;
  &lt;li&gt;Rearranged Scaffolding docs page to split fixed and fluid grid systems.&lt;/li&gt;
  &lt;li&gt;Tons of docs updates for typos and language changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a full list of bug fixes in this release, check out &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?milestone=8&amp;amp;state=closed&quot;&gt;the 2.0.1 milestone&lt;/a&gt; on GitHub. All in all, we closed over 100 issues with over 150 commits—not bad for a patch release! A big thanks to all who reported bugs and added pull requests, we couldn’t do this without you nerds.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Scope CSS classes with prefixes</title>
   <link href="https://markdotto.com/2012/02/16/scope-css-classes-with-prefixes/"/>
   <updated>2012-02-16T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/02/16/scope-css-classes-with-prefixes</id>
   <content type="html">&lt;p&gt;When building a CSS design system like &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;, it’s important to keep things simple, durable, and flexible. This is no easy task, especially on larger teams and projects where the number of components can become quite high. To help improve this situation in a CSS design system, you might consider using prefixed classes instead of chained classes.&lt;/p&gt;

&lt;p&gt;Taking the &lt;strong&gt;chained classes&lt;/strong&gt; approach, your CSS selectors might look something like this for a given set of components:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.btn.success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;..&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.alert.success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We have here a global base class, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.success&lt;/code&gt;, that might house all the commonalities between successful buttons and alerts. Then, at the individual component level, we add on or override as necessary. However, this wide open class and chained approach exposes developers to a number of questions and potential paint points:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What’s that base class stand for?&lt;/li&gt;
  &lt;li&gt;What elements will be affected at the root level?&lt;/li&gt;
  &lt;li&gt;How many elements have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.success&lt;/code&gt; chained onto them?&lt;/li&gt;
  &lt;li&gt;Can it be extended further to more components?&lt;/li&gt;
  &lt;li&gt;What if one instance of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.success&lt;/code&gt; uses green text on a white background while another uses white text on a green background?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And those questions barely scratch the surface. This solution isn’t necessarily bad, but when scale, brevity, and flexibility are your top requirements, it might not be the best idea. A better solution might be using prefixed classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prefixed classes&lt;/strong&gt; guide developers towards a simpler and more maintainable direction for building an extensive CSS design system. Here’s what we have if we take away the generic base class and scope things per component with prefixes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;&lt;span class=&quot;nc&quot;&gt;.btn-success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.alert-success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This way, &lt;strong&gt;the base class is at the component level&lt;/strong&gt; and not the entire system level. In other words, our base classes have become &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.btn&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.alert&lt;/code&gt;, not &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.success&lt;/code&gt;. There’s no bleeding of styles or behavior from one component to another here because we treat components in a “successful state” as an idea across the design system. That is to say, we have a shared &lt;em&gt;idea&lt;/em&gt; of what “success” looks for buttons and alerts, but the &lt;em&gt;execution&lt;/em&gt; is scoped entirely to each independent component. No questions of where common styles are used and no concern of unintended effects, making each component more durable and flexible.&lt;/p&gt;

&lt;p&gt;While a very tactical and detail-oriented practice, building components that inherently isolate themselves for improved modularity and customization in a system like Bootstrap makes for better code and a more enjoyable project down the line.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Slides posted from the Twitter Open Source Summit</title>
   <link href="https://markdotto.com/2012/02/06/slides-posted-from-the-twitter-open-source-summit/"/>
   <updated>2012-02-06T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/02/06/slides-posted-from-the-twitter-open-source-summit</id>
   <content type="html">&lt;script src=&quot;http://speakerdeck.com/embed/4f298b85c7d1bf001f016eec.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;If you didn’t have a chance to make it out to last week’s event, you can view the slides on &lt;a href=&quot;http://speakerdeck.com&quot;&gt;Speaker Deck&lt;/a&gt; from &lt;a href=&quot;http://speakerdeck.com/u/mdo/p/bootstrap-2&quot;&gt;our Bootstrap 2 announcement&lt;/a&gt; at Twitter HQ. In our presentation, Jacob and I walked through a brief update and history of Bootstrap, some of the new hotness in v2, and a quick look at the future of the toolkit. Also, be sure to check out the slides from &lt;a href=&quot;https://twitter.com/sayrer&quot;&gt;Rob Sayre&lt;/a&gt;’s &lt;a href=&quot;http://speakerdeck.com/u/sayrer/p/hoganjs&quot;&gt;Hogan.js talk&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/seanherron&quot;&gt;Sean Herron&lt;/a&gt;’s &lt;a href=&quot;http://speakerdeck.com/u/seanherron/p/opennasa-twitter-open-source-summit&quot;&gt;NASA &amp;amp; Open Source talk&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks again to all those who made it out, helped test &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap 2&lt;/a&gt;, and contributed to the project. We couldn’t do it without you nerds!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootstrap 2 ready for testing and feedback</title>
   <link href="https://markdotto.com/2012/01/24/bootstrap-2-ready-for-testing-and-feedback/"/>
   <updated>2012-01-24T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/01/24/bootstrap-2-ready-for-testing-and-feedback</id>
   <content type="html">&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Bootstrap 2 is out and ready for you to dive in. Head over to &lt;a href=&quot;http://getbootstrap.com&quot;&gt;http://getbootstrap.com&lt;/a&gt; to check it out!&lt;/p&gt;

&lt;p&gt;My fellow nerds, I’m very happy to announce that &lt;a href=&quot;http://twitterbootstrap2.eventbrite.com/&quot;&gt;Bootstrap 2 drops January 31&lt;/a&gt;. To ensure we have the very best release possible, we’re opening up the branch and encouraging everyone to jump in and test the new code. We have a lot of new features, rewritten documentation, and use cases to test with the addition of media queries.&lt;/p&gt;

&lt;p&gt;This week at Twitter is Hack Week and Jacob and I have dedicated the entire week to working on Bootstrap 2 to get ready for the release. There’s a ton to do, but we’re confident we can get it all done with your help testing and providing feedback on the new hotness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s how you can help:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Head on over to GitHub and &lt;a href=&quot;https://github.com/twitter/bootstrap/tree/2.0-wip&quot;&gt;checkout the branch&lt;/a&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.0-wip&lt;/code&gt;. It’s our essentially our master branch right now.&lt;/li&gt;
  &lt;li&gt;Don’t want to check out any code? We’re &lt;a href=&quot;http://markdotto.com/bs2/docs/index.html&quot;&gt;hosting the latest version of the docs&lt;/a&gt; so you can easily load it up on devices and such for testing. (Please don’t host any other version of the docs for now!)&lt;/li&gt;
  &lt;li&gt;Load up the new docs in your favorite (or, ideally, your least favorite) browser or device and start testing.&lt;/li&gt;
  &lt;li&gt;When you find a bug or have feedback, &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?sort=created&amp;amp;direction=desc&amp;amp;state=open&quot;&gt;open a new issue on GitHub&lt;/a&gt;. Tag it as &lt;strong&gt;2.0-wip&lt;/strong&gt; right away so we know to prioritize it. Please include as much context and information as possible. If it’s a visual bug, please include a screenshot. If it pertains to javascript, consider including a &lt;a href=&quot;http://jsfiddle.net/&quot;&gt;jsfiddle&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;If it’s a code fix you can make yourself, go ahead and submit a pull request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.0-wip&lt;/code&gt;. Be sure to read the &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/Contributing-to-Bootstrap&quot;&gt;Contributing to Bootstrap&lt;/a&gt; wiki page first though for a bit of insight into our code practices. (Unsure how to submit a pull request? &lt;a href=&quot;http://help.github.com/send-pull-requests/&quot;&gt;Learn more here&lt;/a&gt;.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re super close to getting Bootstrap 2 out, but we need your help to make it the best it can be. Any help you can spare would be fantastic and much appreciated.&lt;/p&gt;

&lt;p&gt;Thanks in advance, and see you next Tuesday with the finished release!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootstrap in A List Apart No. 342</title>
   <link href="https://markdotto.com/2012/01/17/bootstrap-in-a-list-apart-342/"/>
   <updated>2012-01-17T00:00:00+00:00</updated>
   <id>https://markdotto.com/2012/01/17/bootstrap-in-a-list-apart-342</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://www.alistapart.com/articles/building-twitter-bootstrap/&quot;&gt;&lt;img src=&quot;/uploads/2012/01/bootstrap-ala.png&quot; alt=&quot;Bootstrap in A List Apart&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not too long ago I was asked by the A List Apart crew to contribute an article on &lt;a href=&quot;https://twitter.github.com/bootstrap&quot;&gt;Bootstrap&lt;/a&gt;. After some delays due to the Twitter redesign, the holidays, and some run-ins with the flu, I’m very happy to announce that the article has been published in &lt;a href=&quot;http://www.alistapart.com/issues/342&quot;&gt;today’s new edition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The article, &lt;a href=&quot;http://www.alistapart.com/articles/building-twitter-bootstrap/&quot;&gt;Building Twitter Bootstrap&lt;/a&gt;, focuses on the decisions and processes that went into creating Bootstrap. In short, a super small group of developers and I got together to design and build a new internal tool and saw an opportunity to do something more. Through that process, we saw ourselves build something much more substantial than another internal tool. Months later, we ended up with an early version of Bootstrap as a way to document and share common design patterns and assets within the company.&lt;/p&gt;

&lt;p&gt;After a year of working on it on nights and weekends, we &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;open-sourced Bootstrap&lt;/a&gt; in late August 2010. It’s since become the most popular project on GitHub with over 14,000 watchers and 2,400 forks. There’s a lot more in store for Bootstrap, including v2 launching in the coming weeks, and I couldn’t be more excited about the coming months at Twitter.&lt;/p&gt;

&lt;p&gt;Also, a special thanks to &lt;a href=&quot;http://aworkinglibrary.com/&quot;&gt;Mandy Brown&lt;/a&gt; and &lt;a href=&quot;http://kristastevens.com/&quot;&gt;Krista Stevens&lt;/a&gt; as editors for the article. Without Mandy’s incredible ideas and insightfulness, and Krista’s editing and article preparation, the article wouldn’t have happened. It’s been a pleasure working with both and I hope to do so again in the future.&lt;/p&gt;

&lt;p&gt;Head on over to A List Apart and &lt;a href=&quot;http://www.alistapart.com/articles/building-twitter-bootstrap/&quot;&gt;give it a read&lt;/a&gt;.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>New grid system coming to Bootstrap 2</title>
   <link href="https://markdotto.com/2011/12/16/new-grid-system-coming-to-bootstrap-2/"/>
   <updated>2011-12-16T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/12/16/new-grid-system-coming-to-bootstrap-2</id>
   <content type="html">&lt;p&gt;Bootstrap 2 brings &lt;a href=&quot;http://www.markdotto.com/2011/10/21/making-bootstrap-responsive/&quot;&gt;new responsive features&lt;/a&gt; and a large part of that is the grid system at its core. With BS2, we’ll be leaving behind our 16-column overlords and &lt;strong&gt;moving to a flexible 12-column grid system&lt;/strong&gt;. Nothing substantial should change in your use of Bootstrap, but I wanted to share some thoughts about this new (to Bootstrap) approach.&lt;/p&gt;

&lt;p&gt;To date, mobile and tablet devices were all virtually ignored. No more–Bootstrap 2 will provide support for mobile devices out of the gate. Responsive features will be available and should provide at least some level of support for all our major components.&lt;/p&gt;

&lt;p&gt;By leaving the 16-column grid system behind, we save some headaches and streamline some code. 16-columns required extra CSS for a 3-column layout and we were including an extra 8 columns for those wishing to add 24-column support. No more. We’ve removed the extra CSS and gone to 12-columns, all while retaining the same overall default site width (940px) and adding responsive variations.&lt;/p&gt;

&lt;p&gt;Not much changes for those using Bootstrap when we release 2.0. We’ve been using this grid in the our development of 2.0 for several weeks now and are quite fond of it. Just be sure to check your column sizes and test your projects on mobile and tablet devices when you upgrade.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Follow along with Bootstrap 2’s development on GitHub with the &lt;a href=&quot;https://github.com/twitter/bootstrap/tree/2.0-wip&quot;&gt;2.0-wip&lt;/a&gt; branch.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CSS commenting strategy</title>
   <link href="https://markdotto.com/2011/12/12/css-commenting-strategy/"/>
   <updated>2011-12-12T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/12/12/css-commenting-strategy</id>
   <content type="html">&lt;p&gt;After a few recent projects, I’ve realized a good commenting strategy is necessary in CSS (and any other language really). After running into problems of our own with mysterious or vague code, I figure I’ll share my general set of quick and flexible guidelines for commenting in CSS.&lt;/p&gt;

&lt;p&gt;Here’s what my typical (non-LESS) CSS file looks like:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1437207.js?file=General%20CSS%20formatting&quot;&gt;&lt;/script&gt;

&lt;p&gt;To start, each file should include a repeated name and short description. While the name here can be the same as the filename (as I’ve indicated), combined with the description, it can help you add clarity for other designers. For instance, if you compile multiple CSS files, these comments can guide you in reading the final file.&lt;/p&gt;

&lt;p&gt;Moving along, every major component is broken down into its own section. Not shown above is that each section has two to three lines after it to space things out. Subsections of that component have their own sub headings as well to further break things apart for readability and documentation.&lt;/p&gt;

&lt;p&gt;Really though, the last two types of comments are the most important to me. The others are honestly more of a formality and sanity check as searching is just as fast in most cases. These last two are what keep you and your coworkers happy. Take this example of a typical comment and snippet of CSS:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1437229.js?file=Generic%20CSS%20comment&quot;&gt;&lt;/script&gt;

&lt;p&gt;The comment adds no value to anyone because it doesn’t tell you &lt;em&gt;why&lt;/em&gt; this code is there in the first place. Here’s what might work a bit better:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1437233.js?file=Better%20CSS%20comment&quot;&gt;&lt;/script&gt;

&lt;p&gt;While not the greatest example in the world, it illustrates the point. The last type of commenting, inline notes, works well with this as it provides line-by-line justification for properties. Even though some folks might know &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\9&lt;/code&gt; is an Internet Explorer hack, not everyone does and comments don’t hurt anyone.&lt;/p&gt;

&lt;p&gt;CSS, and any code for that matter, is much more legible and maintainable with the right comments. The why’s and inline context matter most for justifying why blocks of code appear in your files in the first place. Most importantly, commenting makes or breaks a team’s ability to quickly execute and update projects. Figure out your own solution, carry it through, and watch your projects become easier to maintain.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Formatting vendor-prefixed CSS</title>
   <link href="https://markdotto.com/2011/12/06/formatting-vendor-prefixed-css/"/>
   <updated>2011-12-06T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/12/06/formatting-vendor-prefixed-css</id>
   <content type="html">&lt;p&gt;I’m a sucker for CSS conventions. Beyond CSS property order, general code formatting, spacing, and commenting are all up for some discipline. To keep things nice and tidy, and to save time in the future, I do my best to streamline my code. Figuring out the right formatting for CSS properties, especially properties like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;, is near the top of my list.&lt;/p&gt;

&lt;p&gt;Take for instance this block of CSS:&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1436739.js?file=Unformatted%20vender-prefixed%20CSS&quot;&gt;&lt;/script&gt;

&lt;p&gt;Straightforward enough. We have our vendor prefixes first, ordered by character length (a complex of mine I’m afraid), and ending with the official spec for that property. Great, but we can do better!&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1436745.js?file=Formatted%20vender-prefixed%20CSS&quot;&gt;&lt;/script&gt;

&lt;p&gt;Ah, much better! Why? Well, if you’re a fan of code editors like Textmate, Coda, or Sublime Text 2, then you can easily edit multiple lines at a time. In Sublime Text 2—my editor of choice—I just have to hold Option while clicking and dragging to select multiple lines to edit.&lt;/p&gt;

&lt;p&gt;With the values lined up, I can not only read my code faster and easier, but I can edit it faster and easier as well. A little bit of guidance on code formatting goes a long way for your own sanity, and those of your peers.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>CSS property order</title>
   <link href="https://markdotto.com/2011/11/29/css-property-order/"/>
   <updated>2011-11-29T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/11/29/css-property-order</id>
   <content type="html">&lt;p&gt;CSS property order matters, especially on larger teams with several engineers and designers all contributing code. I know it’s been discussed, but frankly there’s always room for improvement and alternate approaches. In a few projects at Twitter, we added the constraint of consistent CSS property order to make onboarding new folks easier, debugging faster, and expectations of what exactly a block of CSS does &lt;em&gt;that&lt;/em&gt; much clearer (without viewing it in the browser).&lt;/p&gt;

&lt;h2 id=&quot;high-level-overview&quot;&gt;High level overview&lt;/h2&gt;

&lt;p&gt;At a high level, here’s our breakdown:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;position&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;display&lt;/code&gt; and box model&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;font&lt;/code&gt;, leading, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;color&lt;/code&gt;, text&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;CSS3 properties like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;and a handful of other purely visual properties&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We hadn’t really seen an approach like this in any other projects we’ve worked on. It mixes the common structural and alphabetical approaches into one in an effort to ensure our property order is logical, scannable, and all-encompassing. We wanted an order that mapped to how we mentally visualized DOM elements and—to an extent—how Webkit’s Inspector presents properties.&lt;/p&gt;

&lt;h2 id=&quot;show-me&quot;&gt;Show me!&lt;/h2&gt;

&lt;p&gt;Getting more specific, here are some blocks of CSS might look with this property order in mind.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1371848.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;Here you can see positioning, box model (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;height&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;padding&lt;/code&gt;), and visual (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-color&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-bottom&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt;) in their proper order. This flows in such a way that you can discern that this is a fixed dark gray bar with a drop shadow–you know exactly what it is you’re dealing with as you read line-by-line.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/1371874.js&quot;&gt; &lt;/script&gt;

&lt;p&gt;In this example, we have only box model and visual. Notice that for box model, we have dimensions first with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;min-height&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;padding&lt;/code&gt; (as that adds to the overall width of an element). For the visual elements, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;background-color&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border&lt;/code&gt; come first because those inform you how this element starts to look (e.g., a gray box witha  border). &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;border-radius&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt; follow that because those are additional visual treatments that add to the base look and feel.&lt;/p&gt;

&lt;h2 id=&quot;use-what-works-for-your-team&quot;&gt;Use what works for your team&lt;/h2&gt;

&lt;p&gt;This approach seems to work well for us and our teams without adding too much overhead. All you need to do is create a series of rules and stick to them with your team and this because a very successful tactic for organizing and maintaining CSS. No one solution is &lt;em&gt;teh best&lt;/em&gt;, so keep that in mind and adjust as you go.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing (Unofficial) GitHub Buttons</title>
   <link href="https://markdotto.com/2011/11/26/introducing-unofficial-github-buttons/"/>
   <updated>2011-11-26T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/11/26/introducing-unofficial-github-buttons</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://ghbtns.com&quot;&gt;&lt;img src=&quot;/uploads/2011/11/introducing-github-buttons.png&quot; alt=&quot;GitHub Buttons&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today I’m stoked to announce the release of my &lt;a href=&quot;http://ghbtns.com&quot;&gt;unofficial GitHub buttons&lt;/a&gt;! For months I’ve wanted to provide consistent, easy-to-use links back to my projects’ source and documentation on GitHub. A couple of weeks ago I was finally able to create a decent method of doing just that. Now, I want to share them with everyone and get feedback from the community.&lt;/p&gt;

&lt;h2 id=&quot;functionality&quot;&gt;Functionality&lt;/h2&gt;

&lt;p&gt;For their initial release (and due to lack of time and expertise), functionality is limited to a static link back to your repo and dynamic counts for the number of watchers and forks on any public repo. In the future I’d love to expand on this to support user profiles and—one day—dynamic buttons via oAuth.&lt;/p&gt;

&lt;h2 id=&quot;how-to-use&quot;&gt;How to use&lt;/h2&gt;

&lt;p&gt;Using these new buttons is as easy as adding an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; and setting some paramaters in the URL. It’s fast, easy, and pretty lightweight. The best part is that these are hosted on GitHub pages, which means you don’t need to host the code yourself. Just add and go. It also comes with a few options: watch or fork button, count or no count, and default or large size.&lt;/p&gt;

&lt;div style=&quot;margin: 14px 0;&quot;&gt;
  &lt;iframe src=&quot;http://ghbtns.com/github-btn.html?user=markdotto&amp;amp;repo=github-buttons&amp;amp;type=watch&amp;amp;count=true&amp;amp;size=large&quot; allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;0&quot; width=&quot;170px&quot; height=&quot;30px&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;div style=&quot;margin: 14px 0;&quot;&gt;
  &lt;iframe src=&quot;http://ghbtns.com/github-btn.html?user=markdotto&amp;amp;repo=github-buttons&amp;amp;type=fork&amp;amp;count=true&amp;amp;size=large&quot; allowtransparency=&quot;true&quot; frameborder=&quot;0&quot; scrolling=&quot;0&quot; width=&quot;146px&quot; height=&quot;30px&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;The two buttons above are live examples of Bootstrap’s watcher and fork counts. Everything but the size of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt; is configurable via URL parameters. (This was the easiest and fastest way for me to get this project out the door.)&lt;/p&gt;

&lt;h2 id=&quot;get-it-on-github&quot;&gt;Get it on GitHub&lt;/h2&gt;

&lt;p&gt;You can find &lt;a href=&quot;https://github.com/markdotto/github-buttons&quot;&gt;the source on GitHub&lt;/a&gt;. Feel free to download, fork, or watch it from there. If you have any feedback or want to contribute to the project, go ahead and &lt;a href=&quot;https://github.com/markdotto/github-buttons/issues&quot;&gt;open an issue&lt;/a&gt; or submit a pull request.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Coming in Bootstrap 2: Improved documentation</title>
   <link href="https://markdotto.com/2011/11/21/coming-in-bootstrap-2-improved-documentation/"/>
   <updated>2011-11-21T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/11/21/coming-in-bootstrap-2-improved-documentation</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt; 2 is well under way and has lots of awesome new features and improvements baked in already. One of the most exciting things for me (believe it or not) is the updated documentation.&lt;/p&gt;

&lt;p&gt;With Bootstrap 2, our goals for improving documenation includes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Greater visibility into the variations and options for all components in Bootstrap&lt;/li&gt;
  &lt;li&gt;Less filler and more technical documentation for easier reading and learning&lt;/li&gt;
  &lt;li&gt;Continued use of live examples right alongside the technical details of how to use any component&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’re still not done with it yet, but we’re making lots of progress. Some of the highlights thus far include splitting the docs into several subpages for faster load time and ease of use while also revamping the homepage to contain nearly all our marketing messaging and key links. The idea is to keep Bootstrap accessible to all by bubbling up the easy stuff first and easing into the more detailed information as necessary.&lt;/p&gt;

&lt;p&gt;As always, lots more is planned and if you have feedback, please &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?state=open&quot;&gt;file an issue on GitHub&lt;/a&gt; so we can address it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Breaking down Bootstrap</title>
   <link href="https://markdotto.com/2011/11/14/breaking-down-bootstrap/"/>
   <updated>2011-11-14T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/11/14/breaking-down-bootstrap</id>
   <content type="html">&lt;p&gt;There are at least two ways to approach organizing an entire system of components like &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Everything in a small set of CSS files for compactness, ease of use in building on shared styles, and fewer requests if used via media queries.&lt;/li&gt;
  &lt;li&gt;Individual files for nearly every component for greater customization when compiling, making styles easier and more straight forward to find.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both have their pros and cons, but I’m most anxious in hearing about &lt;em&gt;your&lt;/em&gt; preferred methods. For context, &lt;strong&gt;here is how Bootstrap’s LESS files are structured today:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bootstrap.less&lt;/li&gt;
  &lt;li&gt;variables.less&lt;/li&gt;
  &lt;li&gt;mixins.less&lt;/li&gt;
  &lt;li&gt;reset.less&lt;/li&gt;
  &lt;li&gt;scaffolding.less&lt;/li&gt;
  &lt;li&gt;type.less&lt;/li&gt;
  &lt;li&gt;tables.less&lt;/li&gt;
  &lt;li&gt;forms.less&lt;/li&gt;
  &lt;li&gt;patterns.less&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If we were to split things out even more, &lt;strong&gt;our files could look like this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;bootstrap.less&lt;/li&gt;
  &lt;li&gt;variables.less&lt;/li&gt;
  &lt;li&gt;mixins.less&lt;/li&gt;
  &lt;li&gt;reset.less&lt;/li&gt;
  &lt;li&gt;scaffolding.less&lt;/li&gt;
  &lt;li&gt;grid.less&lt;/li&gt;
  &lt;li&gt;type.less&lt;/li&gt;
  &lt;li&gt;tables.less&lt;/li&gt;
  &lt;li&gt;forms.less&lt;/li&gt;
  &lt;li&gt;navbar.less&lt;/li&gt;
  &lt;li&gt;dropdowns.less&lt;/li&gt;
  &lt;li&gt;tabs-pills.less&lt;/li&gt;
  &lt;li&gt;breadcrumb.less&lt;/li&gt;
  &lt;li&gt;buttons.less&lt;/li&gt;
  &lt;li&gt;alerts.less&lt;/li&gt;
  &lt;li&gt;pagination.less&lt;/li&gt;
  &lt;li&gt;modals.less&lt;/li&gt;
  &lt;li&gt;popovers.less&lt;/li&gt;
  &lt;li&gt;twipsy.less&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While that’s a lot of individual files, it becomes much easier to customize Bootstrap by simply removing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;import&lt;/code&gt; rules from bootstrap.less and recompiling. If Bootstrap were a standalone app, I’d recommend the former, but as it is a customizable toolkit, the latter feels like it could be better. We’re leaning towards the latter with version 2.0–more files, but greater customization for all.&lt;/p&gt;

&lt;p&gt;Thoughts? &lt;a href=&quot;https://twitter.com/twbootstrap&quot;&gt;Tweet&lt;/a&gt; and let us know.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>How to deploy sites via GitHub</title>
   <link href="https://markdotto.com/2011/11/02/how-to-deploy-sites-via-github/"/>
   <updated>2011-11-02T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/11/02/how-to-deploy-sites-via-github</id>
   <content type="html">&lt;p&gt;After &lt;a href=&quot;http://www.markdotto.com/2011/09/23/github-for-website-deployment/&quot;&gt;one my last posts about GitHub&lt;/a&gt; and how it’s saved my ass a number of times, I had a few requests to detail just how I deploy sites with &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;. So, here we go!&lt;/p&gt;

&lt;h2 id=&quot;first-some-background&quot;&gt;First, some background&lt;/h2&gt;

&lt;p&gt;I host this site, and a number of others, with &lt;a href=&quot;http://www.mediatemple.net/go/order/?refdom=markdotto.com&quot;&gt;Media Temple&lt;/a&gt;. My code, however, is verson-controlled with GitHub, where I have a paid account, &lt;a href=&quot;http://github.com/plans&quot;&gt;the $12/month plan&lt;/a&gt;. That’s namely for the remote-hosted private repos they provide, but I also use GitHub to contribute to a few repos, watch numerous others, and of course maintain &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Using GitHub for site deployment is pretty straight forward. However, to get started, you need to have a hosting provider that allows SSH access and has git installed. If you don’t have SSH enabled, search your hosting provider’s docs. If you need to install git, a quick Google search reveals some solid enough posts about it.&lt;/p&gt;

&lt;h2 id=&quot;now-the-how-to&quot;&gt;Now, the how-to&lt;/h2&gt;

&lt;p&gt;After covering the background details, the rest of this how-to assumes you have a paid GitHub account (for the private repo), SSH access enabled, and git installed on your server. Here’s a quick summary of what we’ll be doing:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Setting up a private GitHub repo&lt;/li&gt;
  &lt;li&gt;Cloning your repo locally&lt;/li&gt;
  &lt;li&gt;Add some code&lt;/li&gt;
  &lt;li&gt;Cloning your repo via SSH&lt;/li&gt;
  &lt;li&gt;Handling maintenance&lt;/li&gt;
  &lt;li&gt;Few other tips&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, let’s get to it!&lt;/p&gt;

&lt;h3 id=&quot;1-setup-your-private-github-repo&quot;&gt;1. Setup your private GitHub repo&lt;/h3&gt;

&lt;p&gt;The first step is to &lt;a href=&quot;https://github.com/repositories/new&quot;&gt;create a private repo on GitHub.com&lt;/a&gt;. It’s the same as creating any other repo, you just have to check the right option in the setup and you’re golden.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/09/github-new-repo.png&quot; alt=&quot;New repo on GitHub&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When you create your new repo, just check the option that says “Only the people I specify” for repo access. Now you have a brand new, completely empty, and private repo ready for code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I prefer a private repo for my personal site as I don’t see any point in anyone viewing those files or contributing to them. Feel free to use a public one, but be warned anyone can browse your stuff.&lt;/p&gt;

&lt;h3 id=&quot;2-clone-the-repo-locally&quot;&gt;2. Clone the repo locally&lt;/h3&gt;

&lt;p&gt;Before we can do anything with our repo, we need to clone it locally and add all our code to it. To do so, just snag the URL of the repo. You’ll find it on your new repo’s page on GitHub.com; it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/09/github-private-repo-page.png&quot; alt=&quot;Private repo on GitHub&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Copy that (manually or via the little clipboard icon) and open up your favorite command line tool (I prefer Terminal). Browse to where you’d like to keep your code locally (on a Mac, I prefer Sites) and we’re ready to clone that repo.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;Sites/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;REPO_URL]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If successful, you’ll see something like the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;Initialized empty Git repository &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; ~/Sites/[REPO_NAME]/.git/
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;Warning: You appear to have cloned an empty repository.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That means you’ve successfully cloned your new repo and that it’s empty–all good things. You know have an empty directory called [REPO_NAME] in your sites directory. Now, let’s add code.&lt;/p&gt;

&lt;h3 id=&quot;3-add-your-code&quot;&gt;3. Add your code&lt;/h3&gt;

&lt;p&gt;The key thing about this step isn’t what you add neccesarily, but how you add it. After you paste or move your files into the newly created directory, you have to add, commit, and push your code to GitHub’s remote server. Let’s walk through that step-by-step.&lt;/p&gt;

&lt;p&gt;First, add the files so git can track them:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add .&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then, commit them so you can push:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-am&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;[COMMIT_MESSAGE&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And lastly, push all pending changes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push origin master&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Boom, all your files are now pushed to GitHub’s servers and you’re now ready to get your code on your own server.&lt;/p&gt;

&lt;h3 id=&quot;4-deploy-to-your-site-via-ssh&quot;&gt;4. Deploy to your site via SSH&lt;/h3&gt;

&lt;p&gt;Now that GitHub is tracking your new code, we can connect to your server via command line and pull another copy of it down. To do so, we have to SSH and clone the repo (as we did in Step 2) one more time. I won’t cover &lt;a href=&quot;http://kb.mediatemple.net/questions/16/Connecting+via+SSH+to+your+server#dv&quot;&gt;how to use SSH&lt;/a&gt; here as that’s a bit out of scope, so I’ll use a generic SSH command here:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh username@website.com&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once connected, navigate to your domain and clone the repo once more, this time right to your server:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git clone &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;REPO_URL]&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once the clone is complete, you have all your files on the server and should be ready to rock! Moving forward, keeping your code up to date is just a matter of working remotely, pushing changes to GitHub, and pulling them down to your server when you’re ready.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;upkeep&quot;&gt;Upkeep&lt;/h2&gt;

&lt;p&gt;As I mentioned above, keeping your site up to date is easy so long as you keep both your local and remote code in sync with git. To do so, repeat Step 3 to push code to GitHub, SSH to your server, then pull the updates like so:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ssh username@website.com
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git pull origin master&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Done deal–all your code should be updated.&lt;/p&gt;

&lt;h3 id=&quot;mac-users-using-your-bash_profile&quot;&gt;Mac users: using your .bash_profile&lt;/h3&gt;

&lt;p&gt;If you’re on a Mac, you can use .bash_profile to setup aliases to make Terminal commands &lt;em&gt;that&lt;/em&gt; much easier. To get started, either create or make a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.bashprofile&lt;/code&gt; file in home folder. Open it up and add the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sites&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cd ~/sites'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mdo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'cd ~/Sites/mdo.com'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git add .'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git push origin head'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pull&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git pull'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'pull &amp;amp;&amp;amp; push'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;st&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git status'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;master&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'git checkout master'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sshmdo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'ssh [domain.com@server.com]'&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;alias &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;editbash&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'subl ~/.bash_profile'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Save out the file and open a new tab in Terminal and you can use your new aliases. The above aliases allow me to quickly get to my Sites directory, make git commands super fast, and SSH quickly.&lt;/p&gt;

&lt;h3 id=&quot;additional-resources&quot;&gt;Additional resources&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://cheat.errtheblog.com/s/git&quot;&gt;Git cheat sheet&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://kb.mediatemple.net/questions/1599/Using+SSH+in+Terminal.app+(Mac+OSX)&quot;&gt;Using SSH in Terminal.app&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://help.github.com/mac-set-up-git/&quot;&gt;Setting up Git on your Mac&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://joemaller.com/908/how-to-install-git-on-a-shared-host/&quot;&gt;Installing Git on a shared host&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Good fucking design advice</title>
   <link href="https://markdotto.com/2011/10/31/good-fucking-design-advice/"/>
   <updated>2011-10-31T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/31/good-fucking-design-advice</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Believe in your fucking self. Stay up all fucking night. Work outside of your fucking habits. Know when to fucking speak up. Fucking collaborate. Don’t fucking procrastinate. Get over your fucking self. Keep fucking learning. Form follows fucking function. A computer is a Lite-Brite for bad fucking ideas. Find fucking inspiration everywhere. Fucking network. Educate your fucking client. Trust your fucking gut. Ask for fucking help. Make it fucking sustainable. Question fucking everything. Have a fucking concept. Learn to take some fucking criticism. Make me fucking care. Use fucking spell check. Do your fucking research. Sketch more fucking ideas. The problem contains the fucking solution. Think about all the fucking possibilities.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Just bought this poster from &lt;a href=&quot;http://goodfuckingdesignadvice.com/&quot;&gt;Good Fucking Design Advice&lt;/a&gt; in &lt;a href=&quot;http://goodfuckingdesignadvice.bigcartel.com/product/black-on-fucking-black-poster&quot;&gt;black on fucking black&lt;/a&gt;. It shall serve as a solid reality check everyday once I get it framed and hung. Love it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Floored</title>
   <link href="https://markdotto.com/2011/10/28/floored/"/>
   <updated>2011-10-28T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/28/floored</id>
   <content type="html">&lt;p&gt;Around the middle of this month, &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt; became the &lt;a href=&quot;https://github.com/popular/watched&quot;&gt;fourth most-watched repository&lt;/a&gt; on &lt;a href=&quot;http://github.com&quot;&gt;GitHub&lt;/a&gt;, passing &lt;a href=&quot;http://mxcl.github.com/homebrew/&quot;&gt;Homebrew&lt;/a&gt;, &lt;a href=&quot;http://html5boilerplate.com/&quot;&gt;HTML5 Boilerplate&lt;/a&gt;, and many other high quality, awesome repos. I’m floored, humbled, and, more than anything, ecstatic.&lt;/p&gt;

&lt;p&gt;Given the reception of Bootstrap, I just wanted to recap a few awesome and staggering stats in light of continued efforts to push out v1.4 as soon as possible and continue to jam on v2:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Over 560,000 visits to the repo alone&lt;/li&gt;
  &lt;li&gt;Over 8,700 watchers&lt;/li&gt;
  &lt;li&gt;Over 1,400 forks&lt;/li&gt;
  &lt;li&gt;Over 400 issues closed&lt;/li&gt;
  &lt;li&gt;Over 30 contributors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of that’s huge and is only going to go up as development marches on. Just wanted to say thanks and share some appreciation for all those who have made Bootstrap possible. You guys rock.&lt;/p&gt;

&lt;p&gt;Thanks!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Simple GitHub.com userstyle</title>
   <link href="https://markdotto.com/2011/10/26/simple-github-com-userstyle/"/>
   <updated>2011-10-26T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/26/simple-github-com-userstyle</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;https://github.com&quot;&gt;GitHub&lt;/a&gt; is awesome, amazing, and wonderful. It’s one of the best things that has ever happened to me as a designer and developer. However, I find myself distracted by the background images and styles of the topbar and struggle to skim boatloads of issues on &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;. So, I added a custom userstyle in Chrome to help me out.&lt;/p&gt;

&lt;h2 id=&quot;the-userstyle&quot;&gt;The userstyle&lt;/h2&gt;

&lt;script src=&quot;https://gist.github.com/1308455.js?file=mdo-github-userstyle.css&quot;&gt;&lt;/script&gt;

&lt;p&gt;The header and body changes are purely cosmetic changes based on personal preference, but the change to the issues list helps me work a bit more efficiently on Bootstrap. I hide who submitted the issue and when and unbold the issue names. This way I can see more issues at once and get a larger, bird’s eye view.&lt;/p&gt;

&lt;h2 id=&quot;updated-topbar&quot;&gt;Updated topbar&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/10/github-userstyle-topbar-before-after.png&quot; alt=&quot;GitHub topbar before/after&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;updated-issues-listing&quot;&gt;Updated issues listing&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/10/github-userstyle-issues-before-after.png&quot; alt=&quot;GitHub issues before/after&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;download-on-github&quot;&gt;Download on GitHub&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://gist.github.com/1308455&quot;&gt;Check it out&lt;/a&gt; and fork it on &lt;a href=&quot;https://gist.github.com&quot;&gt;GitHub Gists&lt;/a&gt; if you like.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you’re using Google Chrome, I recommend using &lt;a href=&quot;https://chrome.google.com/webstore/detail/fjnbnpbmkenffdnngjfgmeleoegfcffe&quot;&gt;Stylish&lt;/a&gt; to add userstyles. For Safari, I recommend &lt;a href=&quot;http://code.grid.in.th/&quot;&gt;User CSS&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Making Bootstrap responsive</title>
   <link href="https://markdotto.com/2011/10/21/making-bootstrap-responsive/"/>
   <updated>2011-10-21T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/21/making-bootstrap-responsive</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/uploads/2011/10/bootstrap-docs-responsive-wip.png&quot; alt=&quot;Bootstrap docs&quot; /&gt;&lt;/p&gt;

&lt;p&gt;With v2.0 of &lt;a href=&quot;https://github.com/twitter/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;, we’re going to include some of the core tools developers need to make any project responsive: media queries. As we only just began to implement the responsive features, we’d love some feedback on where we stand thus far and what developers (and designers) expect.&lt;/p&gt;

&lt;h2 id=&quot;the-plan&quot;&gt;The plan&lt;/h2&gt;

&lt;p&gt;So, after a bit of thought and experimentation, here’s how we’re approaching responsiveness in Bootstrap:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Responsive features should be opt-in&lt;/strong&gt;, not opt-out. Why opt-in? Well, responsive design isn’t necessary for every project, but it should be available for those who want it. For that reason, we’re thinking of making a separate file for all our responsive code for developers to enable.&lt;/li&gt;
  &lt;li&gt;Enabling responsiveness should be &lt;strong&gt;straightforward and easy for all skill levels&lt;/strong&gt;. Since we’re considering opt-in for this, we need all skill levels–designers and developers, noobs and pros–to understand how to use it. A separate .less file and compiled stylesheet will both be available.&lt;/li&gt;
  &lt;li&gt;The responsive features &lt;strong&gt;should work for all major platforms and devices&lt;/strong&gt; (kind of a given, right?). Translation? iOS and Android wherever possible, but not likely Blackberry or Windows. (For full transparency, I’ve had absolutely zero experience with the latter two.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-feedback&quot;&gt;The feedback?&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Three simple guidelines thus far&lt;/strong&gt; is just a way to get some ideas in place to align our thinking and communicate our goals with the community. That said, we’d love more feedback and know there are plenty of questions out there to consider, including:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;What resolutions do we support exactly?&lt;/li&gt;
  &lt;li&gt;How much functionality should be supported at each level?&lt;/li&gt;
  &lt;li&gt;Should Internet Explorer be supported in our media queries?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re a developer actively using Bootstrap, I highly encourage you to check out the &lt;a href=&quot;https://github.com/twitter/bootstrap/tree/2.0-wip&quot;&gt;2.0-wip branch on GitHub&lt;/a&gt; and share your feedback via &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?state=open&quot;&gt;GitHub issues&lt;/a&gt; or &lt;a href=&quot;http://twitter.com/twbootstrap&quot;&gt;Twitter&lt;/a&gt;. We’re always looking for more feedback and welcome it at all levels.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Help us refactor forms for Bootstrap 2.0</title>
   <link href="https://markdotto.com/2011/10/10/help-us-refactor-forms-for-bootstrap-2-0/"/>
   <updated>2011-10-10T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/10/help-us-refactor-forms-for-bootstrap-2-0</id>
   <content type="html">&lt;p&gt;While version 2.0 of Bootstrap is a ways off, we’re still thinking about and (ocassionally) working on some of the new stuff we plan to add with that release in a separate branch, 2.0-wip. To that end, we’re reconsidering our approach to how we use forms and form elements within Bootstrap. And we’d love your feedback on our approach thus far.&lt;/p&gt;

&lt;p&gt;(If you’re tracking the development of Bootstrap, I highly encourage you to watch that branch for new activity. &lt;a href=&quot;https://github.com/twitter/bootstrap/tree/2.0-wip&quot;&gt;Check it out on GitHub&lt;/a&gt;.)&lt;/p&gt;

&lt;h2 id=&quot;forms-in-bootstrap-today&quot;&gt;Forms in Bootstrap today&lt;/h2&gt;

&lt;p&gt;In 1.3, form styles are quite generic and wide-reaching. With the “default” styles being a float-left, right-aligned label, we end up having to undo a lot of styles to normalize the form fields. That’s problematic for a few reasons and doesn’t give developers a lot of leeway when building.&lt;/p&gt;

&lt;h2 id=&quot;what-were-thinking-about-for-v20&quot;&gt;What we’re thinking about for v2.0&lt;/h2&gt;

&lt;p&gt;For 2.0, we’re thinking about namespacing certain styles and types of form to provide a better default state and more included options. When we cut the 2.0 branch, our plan was to include at least four types of form layouts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Vertical/stacked&lt;/strong&gt; with left-aligned labels on top of inputs&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Horizontal&lt;/strong&gt; with float-left and right-aligned labels that appear to the side of inputs&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Search&lt;/strong&gt; with a single, super rounded input and one optional button&lt;/li&gt;
  &lt;li&gt;and, &lt;strong&gt;Inline&lt;/strong&gt; with multiple fields and buttons on one “line”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So why do we need these four options? Well, let’s expand on the descriptions and give you some insight:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Vertical forms give us a better default state because the amount of CSS applied to them is super minimal compared to our current method.&lt;/li&gt;
  &lt;li&gt;With the base styles simplified, we make it easy to turn any vertical form into a horizontal one just by swapping a class. Same markup overall with just one different class.&lt;/li&gt;
  &lt;li&gt;Search forms don’t require much extra styling, but making them stand out amongst other generic forms is useful. While &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;type=search&lt;/code&gt; is an option, it’s support is limited and styles erratic.&lt;/li&gt;
  &lt;li&gt;Inline forms are also useful, and while inline fields are technically possible with the vertical forms, this gives us a more durable and scalable option just in case. It’s also needed for inline labels, so there’s that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s what we have so far from the conceptual side. Hopefully this reduces headaches for creating new and maintaining old forms. To help visualize that, here’s an example of the markup we’re thinking about using for vertical/horizontal forms:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;form&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;vertical-form&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;action=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;fieldset&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;control-group&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;control-label&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;element&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;Label name&lt;span class=&quot;nt&quot;&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;controls&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;element&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/fieldset&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here’s how it differs from 1.3 from a technical standpoint:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;It’s more semantic. Instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.clearfix&lt;/code&gt; we use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.control-group&lt;/code&gt; with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fieldset&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Yes, there are more classes here, but that saves us inheritance and performances issues.&lt;/li&gt;
  &lt;li&gt;It makes your two most common form types, verical and horizontal, completely the same save for a single class on the form.&lt;/li&gt;
  &lt;li&gt;It namespaces the form styles so they don’t clash with anything else in your markup, an approach that really shines in large systems like Bootstrap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hopefully this makes sense from both sides now. The code has more classes, but is infinitely more durable and scalable. We add more options while maintaining existing patterns of stacked and horizontal forms.&lt;/p&gt;

&lt;h2 id=&quot;help-us-out&quot;&gt;Help us out?&lt;/h2&gt;

&lt;p&gt;Hopefully this all gels with what you’re thinking and doing as a developer. We’d love to hear your feedback on this approach for forms in v2.0 via &lt;a href=&quot;http://twitter.com/twbootstrap&quot;&gt;Twitter&lt;/a&gt;, &lt;a href=&quot;https://github.com/twitter/bootstrap/issues&quot;&gt;GitHub issues&lt;/a&gt;, or &lt;a href=&quot;http://groups.google.com/group/twitter-bootstrap&quot;&gt;mailing list&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks in advance!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using GitHub for issue tracking</title>
   <link href="https://markdotto.com/2011/10/01/using-github-for-issue-tracking/"/>
   <updated>2011-10-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/10/01/using-github-for-issue-tracking</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;/uploads/2011/09/github-issues.png&quot; alt=&quot;Issues for Bootstrap on GitHub&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.markdotto.com/2011/09/23/github-for-website-deployment/&quot;&gt;Last time I wrote about GitHub&lt;/a&gt;, I focused on how awesome it is for rapid and simple web deployment. It’s super simple to use for versioning, hosting, and getting new and updated code to your website. Beyond that, with a recent update to the web interface, it’s been made more awesome as an issue tracking for &lt;a href=&quot;https://github.com/twitter/bootstrap&quot;&gt;Bootstrap&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;organizing-our-issues-with-milestones&quot;&gt;Organizing our issues with Milestones&lt;/h2&gt;

&lt;p&gt;Without the ability for users and contributors to file issues on GitHub, I’m not sure we would have caught all the bugs, improvements, and feature requests that we did. With well over 200 issues closed on Bootstrap, we weren’t overwhelmed simply because we had the ability to tag each issue and assign them to a milestone.&lt;/p&gt;

&lt;h2 id=&quot;setting-expectations&quot;&gt;Setting expectations&lt;/h2&gt;

&lt;p&gt;The milestone feature is great for two reasons: my own sanity and transparency for everyone else. Each milestone has represents a new release and helps set expectations for others when dates are assigned to them. Setting expectations on an open-source project like Bootstrap is immensely useful for all involved. It shows people that this is a trusted and evolving endeavor; it’s going to be around for awhile.&lt;/p&gt;

&lt;h2 id=&quot;driving-responsibility&quot;&gt;Driving responsibility&lt;/h2&gt;

&lt;p&gt;I can’t recall another project that I’ve worked on with such vigor and determination as Bootstrap. Aside from my core work duties at Twitter and writing on this blog, nothing else has made me more happy to keep doing what I do as a web and product designer. Having issues and pull requests filed against Bootstrap from people all over the world is humbling and rewarding. It’s been a blast to talk through ideas, push back on others, and help people solve problems. I love every moment of it.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;If you have the chance–even if you’re working in a closed, private repo–give the issue tracking and milestone features of GitHub a go. You’ll be thoroughly impressed and should see a noticeable increase in productivity.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Using iA Writer for Mac</title>
   <link href="https://markdotto.com/2011/09/26/using-ia-writer-for-mac/"/>
   <updated>2011-09-26T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/09/26/using-ia-writer-for-mac</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://iawriter.com&quot;&gt;&lt;img src=&quot;/uploads/2011/09/ia-writer.png&quot; alt=&quot;iA Writer for Mac&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For awhile I’ve been writing blog posts just in a plain text or code editor, or even in Pages, but none of those were great options. Either the fonts, colors, or features always got in the way of just busting out content. Enter &lt;a href=&quot;http://www.iawriter.com/&quot;&gt;iA Writer&lt;/a&gt; into my life.&lt;/p&gt;

&lt;p&gt;iA Writer kicks ass for a few reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;After using GitHub for a bit to manage Bootstrap, I’ve gotten accustomed again to &lt;strong&gt;using Markdown&lt;/strong&gt;. Since iA Writer only supports that, and supports it well, I got up and running super quick with the &lt;a href=&quot;http://daringfireball.net/projects/markdown/syntax&quot;&gt;Markdown syntax&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;It’s all plain text&lt;/strong&gt;, which means I can sync everything via Dropbox and have it all backed up and organized. Syncing with Dropbox means no additional service running in the background like &lt;a href=&quot;http://www.hogbaysoftware.com/products/taskpaper&quot;&gt;Taskpaper&lt;/a&gt; requires (my previous, and still awesome, tool of choice).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fast and simple, just the way I like it.&lt;/strong&gt; The app purposely lacks features like customizing background, font, text size, and more. Its goal is to get you in and get you writing, and that’s what I’ve done (I’ve written 8 blog posts this weekend already in iA Writer).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And best yet? It’s only $10 and is designed and built by the team at &lt;a href=&quot;http://www.informationarchitects.jp/en/&quot;&gt;iA&lt;/a&gt;, people who know their stuff when it comes to making awesomely designed experiences.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://itunes.apple.com/app/id439623248?mt=12&quot;&gt;Check it out in the Mac App Store&lt;/a&gt; and see for yourself&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Good design is constant contact</title>
   <link href="https://markdotto.com/2011/09/20/good-design-is-constant-contact/"/>
   <updated>2011-09-20T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/09/20/good-design-is-constant-contact</id>
   <content type="html">&lt;blockquote&gt;
  &lt;p&gt;Constant contact between designers and engineers allowed for seamless integration of function and formal response.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Out of all the things I’ve read about Rams, the notion of “constant contact” is by far the most evocative of my day-to-day job as a designer at Twitter.&lt;/p&gt;

&lt;p&gt;I work with some of the brightest and most talented engineers in the industry and I can honestly say that without the interactions I’ve had with them, my work would go no where. &lt;strong&gt;&lt;a href=&quot;http://www.vitsoe.com/en/gb/about/dieterrams/gooddesign&quot;&gt;Good design&lt;/a&gt; is constant contact.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The dynamic of a designer-engineer pair is perhaps the most highly valued in design. Constant contact with an engineer provides a different point of view, one essential to how we build and iterate on not just code, but product. A great example of this has been working with @fat on Bootstrap.&lt;/p&gt;

&lt;p&gt;Without @fat’s help, we wouldn’t have released it any time close to when we did, we wouldn’t have half the features we do, and we wouldn’t have any javascript plugins, tests, or makefile functionality. Plus, for an engineer, he’s got a great eye for what looks and feels great.&lt;/p&gt;

&lt;p&gt;Again, constant contact is incredibly valuable. It leads to faster iteration and innovation and challenges your assumptions as a designer. It’s good design.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Updated site design</title>
   <link href="https://markdotto.com/2011/09/18/updated-site-design/"/>
   <updated>2011-09-18T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/09/18/updated-site-design</id>
   <content type="html">&lt;p&gt;Decided to give the site a little update by realigning the design. Not much has changed, so here’s the gist:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Streamlined everything by moving to a single column&lt;/li&gt;
  &lt;li&gt;Sidebar is gone, peep the footer&lt;/li&gt;
  &lt;li&gt;Open Sans, baby (served via Google Web Fonts)&lt;/li&gt;
  &lt;li&gt;Updated photo of me to match my avatar elsewhere&lt;/li&gt;
  &lt;li&gt;Less PHP, JS, HTML, and CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And that’s about it. Shed 20 pounds visually and another 10 under the hood. Feels great. Hope you like it!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Welcoming Bootstrap v1.3</title>
   <link href="https://markdotto.com/2011/09/17/welcoming-bootstrap-v1-3/"/>
   <updated>2011-09-17T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/09/17/welcoming-bootstrap-v1-3</id>
   <content type="html">&lt;p&gt;After a few weeks of intense work, @fat and I are proud to announce the latest version of &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;Bootstrap&lt;/a&gt;, 1.3, with a few new features, a boatload of bug fixes, and—best of all—javascript plugins.&lt;/p&gt;

&lt;h2 id=&quot;new-features&quot;&gt;New features&lt;/h2&gt;

&lt;p&gt;Here’s the lowdown on what’s new to Bootstrap 1.3:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Javascript plugins&lt;/strong&gt; for modals, alerts, dropdowns, scrollspy, tabs, tooltips, and popovers. This is huge—you can now bring Bootstrap to life with interactive design components. They also work with jQuery &lt;em&gt;and&lt;/em&gt; Ender.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Massively updated docs&lt;/strong&gt;, for both the main page and for the new javascript plugins. Yes, I consider this a feature—it’s indispensible for developers and designers. More details below!&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Inline labels&lt;/strong&gt; for marking inline content with key visual flags&lt;/li&gt;
  &lt;li&gt;Media thumbnails&lt;/li&gt;
  &lt;li&gt;Breadcrumbs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;new-and-updated-docs&quot;&gt;New and updated docs&lt;/h2&gt;

&lt;p&gt;Now, about those docs: there is a lot of new stuff. We’ve added more example markup and information on how to use Bootstrap’s code with 1.3 and will continue to do so with every release. To that end, here’s an outline of the big changes to the docs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Added complete javascript page with detailed docs for how to use&lt;/li&gt;
  &lt;li&gt;Three complete example pages of using Bootstrap, linked from main docs page with thumbnails&lt;/li&gt;
  &lt;li&gt;Added section for compiling Less, for guidelines on how to recompile Bootstrap with Less&lt;/li&gt;
  &lt;li&gt;Added section for customizing grid variables in Less&lt;/li&gt;
  &lt;li&gt;Added section for code for using pre and code tags&lt;/li&gt;
  &lt;li&gt;Added section for form field sizes that match grid column sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you’re done here, be sure to checkout &lt;a href=&quot;http://twitter.github.com/bootstrap/&quot;&gt;those beautiful new Bootstrap docs here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;we-got-fixed-issues&quot;&gt;We got (fixed) issues&lt;/h2&gt;

&lt;p&gt;Also included in 1.3 is a hefty set of resolved issues from GitHub and other important style changes. Fun fact: to date, we’ve closed over 200 issues on GitHub. That’s huge!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Updated table styles to be just a tad bit more refined&lt;/li&gt;
  &lt;li&gt;Added new form input sizes based on the Bootstrap grid system (meaning now you can do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input.span5&lt;/code&gt; for a 280px-wide input)&lt;/li&gt;
  &lt;li&gt;Removed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:focus&lt;/code&gt; states from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:active&lt;/code&gt; links in Firefox&lt;/li&gt;
  &lt;li&gt;Fixed unqualified &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.clearfix&lt;/code&gt; that added bottom margin to all containers&lt;/li&gt;
  &lt;li&gt;Updated &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.container()&lt;/code&gt; mixing to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fixed-container()&lt;/code&gt; to prevent conflicts when compiling&lt;/li&gt;
  &lt;li&gt;Added focus states (either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;box-shadow&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;outline&lt;/code&gt; on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:focus&lt;/code&gt;) to all buttons, links, and inputs&lt;/li&gt;
  &lt;li&gt;No longer require &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;h3&lt;/code&gt; in topbar, but still support for backwards compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a complete list of issues fixed in 1.3, &lt;a href=&quot;https://github.com/twitter/bootstrap/issues?sort=created&amp;amp;direction=desc&amp;amp;state=closed&amp;amp;page=1&amp;amp;milestone=4&quot;&gt;view the milestone on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Be sure to take a moment and thank your friendly, neighborhood @fat for all the work he’s put into this release. None of the javascript would be here without him and he’s been instrumental in pushing the development of Bootstrap since day one. He’s a boss. Mad props, broheim.&lt;/p&gt;

&lt;p&gt;We’ve also created a new Twitter account, @TwBootstrap, for announcements, feature and release teasing, and open-ended discussion. Be sure to follow along for the latest as we continue on with development.&lt;/p&gt;

&lt;p&gt;Now, go &lt;a href=&quot;https://github.com/twitter/bootstrap&quot;&gt;checkout the latest Bootstrap&lt;/a&gt; on GitHub!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;More links:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Bugs/requests/issues? &lt;a href=&quot;https://github.com/twitter/bootstrap/issues&quot;&gt;File an issue on GitHub&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Need a list of changes? &lt;a href=&quot;https://github.com/twitter/bootstrap/wiki/Changelog&quot;&gt;Full changelogs are available&lt;/a&gt; on the wiki.&lt;/li&gt;
  &lt;li&gt;Want to discuss the project? Subscribe to &lt;a href=&quot;http://groups.google.com/group/twitter-bootstrap&quot;&gt;the Bootstrap Google group&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>Write less Less</title>
   <link href="https://markdotto.com/2011/09/05/write-less-less/"/>
   <updated>2011-09-05T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/09/05/write-less-less</id>
   <content type="html">&lt;p&gt;I’ve written about using &lt;a href=&quot;http://lesscss.org&quot;&gt;LESS&lt;/a&gt; before, touting the benefits of accelerating development and simplifying CSS. It seems the more I use it, the more awesome things I have to say about it. It adds many great features to regular CSS like variables, mixins, and nesting, but it’s the latter that that I want to talk about more today.&lt;/p&gt;

&lt;p&gt;While I’ve written about &lt;a href=&quot;/2011/01/29/an-update-on-less-js-nesting-your-css&quot;&gt;using nesting in LESS&lt;/a&gt; before, turns out it can encourage good and bad practices as a web developer. Nesting is great, but not if you’re just adding bloat to your code. Take for instance this snippet of LESS:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When compiled, it looks like this:&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So, what’s the problem? Looks fine at first, right? Well, not so much. You can actually improve this quite a lot by simplifying the nesting, thereby decreasing the amount of code, rendering time, file size, and most importantly specificity. With CSS, I’ve found you need to strike a balance between writing very generic code and writing very durable and modular code. Specificity as a result of nesting has a direct impact on both of those things.&lt;/p&gt;

&lt;p&gt;Taking that same LESS code from above and rewriting it to not use unecessary parents in our selectors shows how we can attempt to get closer to achieving that balance.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Of course it depends on your markup and your needs, but this is the gist of what I’m getting at. &lt;strong&gt;Ultimately this isn’t a LESS-specific problem;&lt;/strong&gt; anyone coding CSS can run into this, but with LESS it becomes easier to do unintentionally.&lt;/p&gt;

&lt;p&gt;Don’t nest just to nest. Nest to simplify your final, compiled CSS. You’ll save code and headaches later on.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Bootstrap updated</title>
   <link href="https://markdotto.com/2011/05/30/bootstrap-updated/"/>
   <updated>2011-05-30T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/05/30/bootstrap-updated</id>
   <content type="html">&lt;p&gt;It’s been far too quiet around here. As a quick update, I’ve pushed some new changes to &lt;a href=&quot;http://markdotto.com/bootstrap&quot;&gt;Bootstrap&lt;/a&gt; to GitHub for all to enjoy. Included are some commits by those in the community (many thanks!) and some other things I’ve been sitting on for quite some time as part of another project (hopefully that will come soon enough).&lt;/p&gt;

&lt;p&gt;Here’s the standout new stuff from the latest push:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;New gradients with support for direction and IE10 syntax&lt;/li&gt;
  &lt;li&gt;New helper methods for sizing and quick block-level center alignment&lt;/li&gt;
  &lt;li&gt;All variables now in camelCase&lt;/li&gt;
  &lt;li&gt;Opacity added in with some lovely math to support IE&lt;/li&gt;
  &lt;li&gt;Added offset support for columns (to indent them by a number of columns)&lt;/li&gt;
  &lt;li&gt;Namespaced font mixins for more context and add new .shorthand mixin&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More to come soon! In the mean time, head on over to Github to &lt;a href=&quot;https://github.com/markdotto/Bootstrap.less&quot;&gt;download or fork Bootstrap&lt;/a&gt;.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>Fatten up those T's</title>
   <link href="https://markdotto.com/2011/04/15/fatten-up-those-ts/"/>
   <updated>2011-04-15T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/04/15/fatten-up-those-ts</id>
   <content type="html">&lt;p&gt;As Naz Hamid pointed out Thursday, the demand for highly focused specialists in the design community is dwindling and our schools are somewhat responsible. While his post focuses on students fresh out of a degree and embracing “&lt;a href=&quot;http://weightshift.com/memo/the-new-design&quot;&gt;the new design&lt;/a&gt;,” the principle extends beyond students to the rest of the community.&lt;/p&gt;

&lt;p&gt;Generalist specialists—T-shaped people—are the new design hotness.&lt;/p&gt;

&lt;p&gt;The concept isn’t revolutionary, nor impossible for anyone to pursue in their career. As creative individuals, we typically have the luxury (curse?) of having interest in the design of just about anything. Clothing, furniture, cars, and hardware are all common interests amongst people in the Web design community. For many of those people, those interests extend to actual skill backed by a decent amount of experience.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/04/t-shaped.png&quot; alt=&quot;T-shaped people&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For designers on the Web, our skills need to spill into other (previously isolated) verticals. Dedicated graphic designers, visual designers, UX designers, and the like may always find roles down the line, but it seems like the generalist specialists are winning out. That’s where being T-shaped comes in.&lt;/p&gt;

&lt;p&gt;As a T-shaped designer one should have experience across the multiple disciplines with a focus or preference for one or two. Being T-shaped means you can &lt;strong&gt;shift yourself and provide value at just about any stage&lt;/strong&gt; or type of project—like sketching, wireframing, visual design, and code. While you can certainly train yourself to be T-shaped, most of us end up this way no matter what through life’s course.&lt;/p&gt;

&lt;p&gt;If you’re new to a handful of disciplines as a designer, getting to be a T-shaped designer isn’t hard, but it takes time. To get there, you need to fatten up those T’s by getting your feet wet in things you might not have any experience in.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/04/t-shaped-fattened.png&quot; alt=&quot;T-shaped people&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you’re a graphic designer, work towards bringing whatever print experience you have to a small single page site. If you’re an interaction designer, start checking out HTML and CSS, and then move on to some basic jQuery. By doing so, you become a much more versatile designer and contributor on any project.&lt;/p&gt;

&lt;p&gt;Whatever your speciality is, find something close to it and work at it. You gain a richer understanding of your work and can begin to look at projects from various points of view with relative ease.&lt;/p&gt;

&lt;p&gt;So, get out there and &lt;strong&gt;fatten up your T&lt;/strong&gt; by learning something new—you’ll love it, I guarantee it.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Introducing Bootstrap</title>
   <link href="https://markdotto.com/2011/03/21/introducing-bootstrap/"/>
   <updated>2011-03-21T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/03/21/introducing-bootstrap</id>
   <content type="html">&lt;p&gt;&lt;a href=&quot;http://markdotto.com/bootstrap&quot;&gt;&lt;img src=&quot;/uploads/2011/03/bootstrap-preview.png&quot; alt=&quot;Bootstrap&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the last several months, I’ve been developing websites and apps with an awesome tool called &lt;a href=&quot;http://lesscss.org&quot;&gt;LESS&lt;/a&gt;. It’s a CSS preprocessor that sits on top of regular ol’ CSS, but provides a ton of extra features like mixins, variables, functions, and operations. The best part? It all comes out as compressed, locally-stored CSS. Hotness, right?&lt;/p&gt;

&lt;p&gt;Well, when I started using LESS at Twitter to create Blueprint—a CSS and HTML framework that helps our engineers quickly developer Twittery apps—I realized I needed a starter file of sorts to house all my variables and simple mixins. As time went out, that file grew and has since become the soul of every project I work on, including this very website.&lt;/p&gt;

&lt;p&gt;Today, I’m releasing a modified version of that file and it’s called &lt;a href=&quot;http://markdotto.com/bootstrap&quot;&gt;Bootstrap&lt;/a&gt;. Bootstrap is a super awesome pack of mixins and variables to be used in conjunction with LESS in any of your web projects. It immediately makes any new design or development project &lt;em&gt;that&lt;/em&gt; much easier to start, and also makes older projects easier to maintain.&lt;/p&gt;

&lt;p&gt;Looking ahead, I plan on adding more to Bootstrap with additional mixins, variables, and such. I’m also considering making Bootstrap part of several larger projects that I hope to release over the next few months. More on those things to come soon enough!&lt;/p&gt;

&lt;p&gt;For now, &lt;a href=&quot;http://markdotto.com/bootstrap&quot;&gt;visit the Bootstrap website&lt;/a&gt; to find out more. You can &lt;a href=&quot;https://github.com/markdotto/Bootstrap.less&quot;&gt;download or fork it at GitHub&lt;/a&gt;. Questions, comments, or suggestions? Email me.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>One year at Twitter</title>
   <link href="https://markdotto.com/2011/02/01/one-year-at-twitter/"/>
   <updated>2011-02-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/02/01/one-year-at-twitter</id>
   <content type="html">&lt;p&gt;Today marks the one year anniversary of working as a designer at Twitter. The only thing that I can say about it is &lt;em&gt;holy shit&lt;/em&gt;. 2010 came and went faster than any other year I can recall. It was full of awesome events, people, and projects, and 2011 is shaping up to be even better.&lt;/p&gt;

&lt;p&gt;When I started we had less than 140 employees, the design team was 6 people strong, we were on one floor in our building, had a different CEO, and our Promoted Products were just getting started. Flash forward to today and we have 10 people on the design team intermingled with over 350 employees on two floors, a new CEO, and three types of Promoted Products.&lt;/p&gt;

&lt;p&gt;I’m pretty stoked for the next year. I’m looking forward to hunkering down with the rest of the revenue team to continue to iterate on and refine our products, &lt;a href=&quot;http://twitter.com/job.html?jvi=oUkkVfwd,Job&quot;&gt;growing the design team&lt;/a&gt;, and making Twitter more awesome than it is today.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>An update on Less.js &amp; nesting your CSS</title>
   <link href="https://markdotto.com/2011/01/29/an-update-on-less-js-nesting-your-css/"/>
   <updated>2011-01-29T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/01/29/an-update-on-less-js-nesting-your-css</id>
   <content type="html">&lt;p&gt;Awhile back I put together &lt;a href=&quot;/2010/12/18/the-problem-with-nesting-css-with-less-or-sass/&quot;&gt;a short comparison of nesting in Less and Sass&lt;/a&gt; and how to improve it in both stylesheet languages. Tonight I learned I made a critical mistake in my summary of &lt;a href=&quot;http://lesscss.org&quot;&gt;Less&lt;/a&gt;’s nesting features. I have no idea how I missed it, but &lt;a href=&quot;http://davegamache.com&quot;&gt;Dave Gamache&lt;/a&gt; shared this with me tonight and I’m still reeling.&lt;/p&gt;

&lt;p&gt;Here’s how I &lt;em&gt;thought&lt;/em&gt; nesting worked in Less:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;darken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;link-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Based on the documentation that I read, I saw no way of nesting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:hover&lt;/code&gt; selector within the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a&lt;/code&gt; selector right before. Sass allowed for this, so I was at a loss as to why Less wouldn’t do it as well.&lt;/p&gt;

&lt;p&gt;Turns out, I just suck and it is completely possible:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;div#container {
  a {
    color: @link-color;
    &amp;amp;:hover {
      color: darken(@link-color, 25);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thanks, Dave! Now, if you’ll excuse me, I have to go rewrite buckets of CSS to fix my nesting :).&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Daring Fireball user style now on GitHub</title>
   <link href="https://markdotto.com/2011/01/11/daring-fireball-user-style-now-on-github/"/>
   <updated>2011-01-11T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/01/11/daring-fireball-user-style-now-on-github</id>
   <content type="html">&lt;p&gt;Just a heads up that I’ve made my &lt;a href=&quot;/2011/01/01/daring-fireball-user-style/&quot;&gt;Daring Fireball user style available on GitHub&lt;/a&gt;. Head there for the latest and greatest from here on out. Feel free to fork it with any tweaks you might have, too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to use it now?&lt;/strong&gt; Update your user style rules to include an import rule instead of the full-blown CSS I posted previously. It’s a compressed version of the CSS, with some additional updates, hosted on &lt;a href=&quot;http://pages.github.com/&quot;&gt;Github Pages&lt;/a&gt;. Just copy and paste the code below and you should be all set!&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;@import&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;url(&quot;http://markdotto.github.com/mdo-df-min.css&quot;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Be sure to read &lt;a href=&quot;/2011/01/01/daring-fireball-user-style/&quot;&gt;the original blog post&lt;/a&gt; I published a week ago that details some of the modifications I’ve made.&lt;/p&gt;

&lt;p&gt;(Hat tip to @kneath for pointing out GitHub Pages.)&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>3D text using just CSS</title>
   <link href="https://markdotto.com/2011/01/05/3d-text-using-just-css/"/>
   <updated>2011-01-05T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/01/05/3d-text-using-just-css</id>
   <content type="html">&lt;p&gt;I have no idea if it’s been done before, but I’ve long wanted to put together a quick little demo showing the power of CSS’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;text-shadow&lt;/code&gt; property. Turns out the latest versions of Chrome, Safari, Firefox, and Opera all render multiple text-shadows on elements, just like &lt;a href=&quot;http://www.zurb.com/playground/css-boxshadow-experiments&quot;&gt;box shadows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://markdotto.com/playground/3d-text/&quot;&gt;&lt;img src=&quot;/uploads/2011/01/3d-text.jpg&quot; alt=&quot;3D text using just CSS&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I threw this together: 3D text using nothing but CSS. No extra markup, no &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:before&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:after&lt;/code&gt; mess, and no images. Just progressively enhancing CSS to add some flair to your work.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://markdotto.com/playground/3d-text/&quot;&gt;Check out the demo&lt;/a&gt; and let me know what you think!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Daring Fireball user style</title>
   <link href="https://markdotto.com/2011/01/01/daring-fireball-user-style/"/>
   <updated>2011-01-01T00:00:00+00:00</updated>
   <id>https://markdotto.com/2011/01/01/daring-fireball-user-style</id>
   <content type="html">&lt;p&gt;My eyes don’t handle light text on dark backgrounds very well—it physically hurts to even try. I love reading &lt;a href=&quot;http://daringfireball.net&quot;&gt;Daring Fireball&lt;/a&gt;, but if the name sounds familiar, then you know of the small text, dark background, and low contrast.&lt;/p&gt;

&lt;p&gt;Although I read a lot of his posts in &lt;a href=&quot;http://madeatgloria.com/brewery/silvio/reeder&quot;&gt;Reeder for Mac&lt;/a&gt;, I do find myself visiting the full site often. Instead of just whining about it, I figure I’ll whine about it &lt;em&gt;and&lt;/em&gt; do something about it. In comes my Daring Fireball user style.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2011/01/df-custom.png&quot; alt=&quot;Daring Fireball custom CSS by @mdo&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;whats-changed&quot;&gt;What’s changed&lt;/h2&gt;

&lt;p&gt;Here’s the rundown on what it does:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;white background with dark gray text&lt;/li&gt;
  &lt;li&gt;bumped up the font-size&lt;/li&gt;
  &lt;li&gt;eliminated the sidebar’s nav&lt;/li&gt;
  &lt;li&gt;fixed the ads to the bottom left (no need to hide them, they’re good quality)&lt;/li&gt;
  &lt;li&gt;resized the main column to 550px&lt;/li&gt;
  &lt;li&gt;changed out link colors to blue for more contrast&lt;/li&gt;
  &lt;li&gt;and lastly, miscellaneous spacing changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;grab-a-copy&quot;&gt;Grab a copy&lt;/h2&gt;

&lt;p&gt;Go ahead and snag a copy for yourself—just copy and paste the CSS below.&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;/*
  Daring Fireball
  Author: @mdo
  Description: Improves contrast and readability of DF without removing the ads.
*/&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Helvetica&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Neue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Helvetica&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Arial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sans-serif&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Background change and font-size bump */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;40px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;13px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;line-height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;18px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Links to blue! */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#2276BB&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;border-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#eee&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Clean up the text colors and headings */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;h4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.linkedlist&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.article&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.article&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.linkedlist&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.article&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;border-left-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#ccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.linkedlist&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;.article&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;blockquote&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#777&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;/* Remove top margin from all img elements */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;/* Remove left margin on dd */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;dl&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.linkedlist&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;/* Site Container */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Box&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;550px&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;/* Masthead */&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Banner&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;/* Modify the logo */&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Banner&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;padding-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;padding-right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;-webkit-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;/* Hide shirts promo */&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#BannerPromo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;/* Nix the sidebar and widen the main column */&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Sidebar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;/* Hide everything in the sidebar but the ads */&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Sidebar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Sidebar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;/* Move the ads, because ads are revenue and revenue is nice */&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fixed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;15px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;20px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;160px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;margin-bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.ads&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;text-align&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#SidebarTheDeck&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.the_deck_promo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;margin-top&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;/* Reposition the main column */&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#Main&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;50px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;!important&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Not sure how to use it? Check out these extensions for your favorite browsers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Safari:&lt;/strong&gt; &lt;a href=&quot;http://code.grid.in.th/&quot;&gt;User CSS&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Chrome:&lt;/strong&gt; &lt;a href=&quot;https://chrome.google.com/extensions/detail/fjnbnpbmkenffdnngjfgmeleoegfcffe&quot;&gt;Stylish&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Firefox:&lt;/strong&gt; &lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/2108/&quot;&gt;Stylish&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enjoy!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>The problem with nesting CSS with Less or Sass</title>
   <link href="https://markdotto.com/2010/12/18/the-problem-with-nesting-css-with-less-or-sass/"/>
   <updated>2010-12-18T00:00:00+00:00</updated>
   <id>https://markdotto.com/2010/12/18/the-problem-with-nesting-css-with-less-or-sass</id>
   <content type="html">&lt;p&gt;I’m a big fan of using &lt;a href=&quot;LESS&quot;&gt;http://lesscss.org/&lt;/a&gt; with all my coding projects (be sure to read my other post for more details on it). It saves time by providing me variables, mixins, and of course nesting rules. &lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; does the same thing, but for one reason or another I never could get used to it’s syntax. The problem with nesting, and a problem I see in CSS all too often is over-specificity.&lt;/p&gt;

&lt;p&gt;Here’s an example of nested rules in Less:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;darkGray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;ul#nav&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;err&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s a simpler way to write out your CSS, but does it really pay off?  That depends on how you look at it. On the one hand, it streamlines your code and provides an easy way to determine the structure of the markup that it styles. On the other hand, it’s way too specific when Less parses it out as regular ol’ CSS.&lt;/p&gt;

&lt;p&gt;Here’s that same block, but as parsed as plain CSS:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#nav&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#nav&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;#nav&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is a bit of an oversimplification, but it’s easy to see what’s going on here. You can easily rewrite that CSS to be less specific, but just as effective. CSS is most effective when it is just specific enough, but doesn’t overdo it.&lt;/p&gt;

&lt;p&gt;Here’s that parsed CSS again, but without the inheritance from nesting:&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;ul&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;li&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;#header&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;inline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The problem with this is again one of over-specificity and speed. Browsers read CSS right to left, and the most specific you get, the longer it takes for the browsers to parse your CSS. This isn’t an issue on most sights as the difference is in milliseconds, but for certain circumstances, I can see it being problematic.&lt;/p&gt;

&lt;p&gt;Either way, nesting without prefacing selectors with it’s parent rule would be outstanding. Nesting is primarily saves on time and readability, so shouldn’t that be reflected in the output of Less and Sass? Perhaps in future iterations.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>WebKit placeholder text color</title>
   <link href="https://markdotto.com/2010/08/30/webkit-placeholder-text-color/"/>
   <updated>2010-08-30T00:00:00+00:00</updated>
   <id>https://markdotto.com/2010/08/30/webkit-placeholder-text-color</id>
   <content type="html">&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;phone&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;placeholder=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;xxx-xxx-xxxx&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;::-webkit-input-placeholder&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;#ccc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://anthonyshort.com.au/post/830446097/change-the-colour-of-input-placeholder-text&quot;&gt;Anthony Short&lt;/a&gt; shows us how to change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;placeholder&lt;/code&gt; text for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;input&lt;/code&gt; fields in WebKit browsers.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>About the new design</title>
   <link href="https://markdotto.com/2010/08/25/about-the-new-design/"/>
   <updated>2010-08-25T00:00:00+00:00</updated>
   <id>https://markdotto.com/2010/08/25/about-the-new-design</id>
   <content type="html">&lt;p&gt;The other day I quickly coded a new design for this here website. The idea behind it is simple: provide some base structure, but ultimately let the content drive the design of the site. To share what’s under the hood, I wanted to share a little more about that idea and what’s powering this site.&lt;/p&gt;

&lt;h2 id=&quot;form-before-function&quot;&gt;Form Before Function&lt;/h2&gt;

&lt;p&gt;That phrase feels like a cop-out, but it sums things up nicely. So far, photos and a few text and code heavy posts are all that’s here. That could easily change and I wanted to remain flexible as to not feel constrained by whatever elaborate design I could come up with.&lt;/p&gt;

&lt;p&gt;I don’t know exactly what I want out of this site yet, only that I want to blog, share photos, talk about some code, and share thoughts on links.&lt;/p&gt;

&lt;h2 id=&quot;under-the-hood&quot;&gt;Under the Hood&lt;/h2&gt;

&lt;p&gt;Because it’s what I’m familiar with, I opted to use WordPress once again. Coupled with the awesome plugin support and flexibility of WordPress as a CMS, it was a no-brainer for me. Here’s a look at what I’m using with WordPress to power this site.&lt;/p&gt;

&lt;h3 id=&quot;categories-not-custom-posts&quot;&gt;Categories, Not Custom Posts&lt;/h3&gt;
&lt;p&gt;Just a quick note to begin here: WordPress 3.x allows for custom post types. I’ve used them before, but decided to avoid them this time around and instead keep things simple to start. As I said, I want the form of this blog to come as naturally as possible.&lt;/p&gt;

&lt;p&gt;To customize how each category’s post shows up, I threw in some conditionals for the loop:&lt;/p&gt;

&lt;div class=&quot;language-php highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;have_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;have_posts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in_category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'photos'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;figure&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;figcaption&amp;gt;&lt;/span&gt;
        **&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;**
        &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_post_meta&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;'caption'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figcaption&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;elseif&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;in_category&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'quotes'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;blockquote&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_concept&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nt&quot;&gt;&amp;lt;cite&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_excerpt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/cite&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/blockquote&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tweetbutton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;date&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'l, F jS, Y'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;hr&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;endwhile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;cp&quot;&gt;?&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;plugin-wp-tweet-button&quot;&gt;Plugin: &lt;a target=&quot;_blank&quot; href=&quot;http://wordpress.org/extend/plugins/wp-tweet-button/&quot;&gt;WP Tweet Button&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;To encourage sharing of the articles I (will) write, I’ve added the Twitter Tweet button via this handy plugin. It gives you a few options, including: automagically adding it to posts, custom recommendations per post, and more.&lt;/p&gt;

&lt;p&gt;Check it out if you haven’t yet. I did try some other plugins but they all sucked. This one seemed best.&lt;/p&gt;

&lt;h3 id=&quot;plugin-disable-wpautop&quot;&gt;Plugin: &lt;a target=&quot;_blank&quot; href=&quot;http://urbangiraffe.com/plugins/disable-wpautop/&quot;&gt;Disable WPAutoP&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I can’t begin to tell you just how frustrating WordPress’s automatic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; tags are. They wrap anything and everything, which makes for some funky styling if you’re not careful enough (e.g., images get wrapped and can leave funky spacing if floated). Install this bad boy and kiss those rogue &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;p&lt;/code&gt; tags good-bye.&lt;/p&gt;

&lt;h3 id=&quot;css-with-lessjs&quot;&gt;CSS with &lt;a target=&quot;_blank&quot; href=&quot;http://github.com/cloudhead/less.js&quot;&gt;Less.js&lt;/a&gt;&lt;/h3&gt;

&lt;p&gt;I talked about this before, but I’ll mention it here again. Less.js, a Javascript implementation of Less CSS (previously done via Ruby) that gives you powerful add-ons to CSS. Use it to add variables, create mixins for shorthanding long or complicated pieces of code, perform math, and more. It’s really handy.&lt;/p&gt;

&lt;p&gt;Plus, even though it compiles the CSS in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; of your page, it stores it in a HTML5 local database. Hot.&lt;/p&gt;

&lt;h3 id=&quot;chili-a-jquery-syntax-highlighter&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://plugins.jquery.com/project/chili&quot;&gt;Chili&lt;/a&gt;: A jQuery Syntax Highlighter&lt;/h3&gt;

&lt;p&gt;Not sure if there is a better one out there, but it seemed solid to me after a quick tour around Google. I’ve love some suggestions for alternatives; my only complaint is it’s ugly default styling. Will definitely need to dive in and change that up more in the future.&lt;/p&gt;

&lt;h3 id=&quot;paintbrushjs-javascript-image-modification&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;http://mezzoblue.github.com/PaintbrushJS/&quot;&gt;PaintbrushJS&lt;/a&gt;: Javascript Image Modification&lt;/h3&gt;

&lt;p&gt;I use PaintbrushJS to modify that beautiful mug of mine on your left. It’s damned awesome; you can &lt;a target=&quot;_blank&quot; href=&quot;http://mezzoblue.github.com/PaintbrushJS/demo/&quot;&gt;modify images&lt;/a&gt; with sepia, noise, tint, and even blur filters. All on the fly with javascript and some awesome use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;canvas&lt;/code&gt;. It’s developed by &lt;a target=&quot;_blank&quot; href=&quot;http://mezzoblue.com&quot;&gt;Dave Shea&lt;/a&gt; (@&lt;a target=&quot;_blank&quot; href=&quot;http://twitter.com/mezzoblue&quot;&gt;mezzoblue&lt;/a&gt;) and is just getting started. Not practical in my implementation, no, but still cool :).&lt;/p&gt;

&lt;h3 id=&quot;beanstalk-for-low-maintenance-svn&quot;&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://beanstalkapp.com/&quot;&gt;Beanstalk&lt;/a&gt; for Low Maintenance SVN&lt;/h3&gt;

&lt;p&gt;I’m a fan of version control—if by version control you mean just one master branch of all my code so that I can quickly revert my mistakes and checkout new copies should my server get hacked or otherwise fubared. Nice to have and these guys do all the leg work; I just import my base files and they take it from there.&lt;/p&gt;

&lt;p&gt;Also, an added bonus of using SVN was the need for using SSH to checkout my code on my server. Handle to know; I need to pick up more stuff like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And that’s it!&lt;/strong&gt; I’ll keep adding features and posting about them as I go though.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Like CSS3? Use LESS.js</title>
   <link href="https://markdotto.com/2010/08/23/like-css3-use-less-js/"/>
   <updated>2010-08-23T00:00:00+00:00</updated>
   <id>https://markdotto.com/2010/08/23/like-css3-use-less-js</id>
   <content type="html">&lt;p&gt;I’ve been using &lt;a href=&quot;http://github.com/cloudhead/less.js&quot;&gt;Less.js&lt;/a&gt; in just about every project I can lately and I love it. I don’t go wild about it though; I’d rather preserve the readability and structure of regular ol’ CSS. That said, I do want to make more complex things easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But wait, why use it?&lt;/strong&gt; Well, for a few reasons really, but most importantly to add variables for repeated values like colors and to simplify the usage of CSS3 values that have vendor prefixes.&lt;/p&gt;

&lt;p&gt;So here are a few examples of how I use Less.js. Check them out and feel free to use them in your own code.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// This is a comment&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* This is also a comment */&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Comments:&lt;/strong&gt; Less.js brings a small add-on for me, but for some reason I love it.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Colors&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@linkColor&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;#4bb14b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@darkGray&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;#333&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;@lightGray&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;#7f7d79&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Colors as variables:&lt;/strong&gt; Hex values can be a real headache, especially if you change them often. Use variables instead to save yourself the pain.&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;darken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linkColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Additional functions: darken, saturate, desaturate,&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;greyscale&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Functions:&lt;/strong&gt; One of my new favorite features is functions in Less.js. I use them on my link hovers. &lt;a href=&quot;http://github.com/cloudhead/less.js/functions&quot;&gt;More info&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-scss highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Declare border-radius for everyone (yay!)&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;borderRadius&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; (@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;5px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;-khtml-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;-moz-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;-webkit-border-radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;radius&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;boxShadow&lt;/span&gt;&lt;span class=&quot;err&quot;&gt; (@&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,.&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;-moz-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;-webkit-box-shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shadow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;#fff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;30px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nl&quot;&gt;margin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.borderRadius&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;6px&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;nc&quot;&gt;.boxShadow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;1px&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;3px&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;rgba&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;CSS3 mixins:&lt;/strong&gt; With Less.js, you can use what’s called mixins—partials for your CSS.&lt;/p&gt;

&lt;p&gt;Have a suggestion? Talk to me on Twitter or shoot me an email.&lt;/p&gt;
</content>
 </entry>
 

</feed>
