Ulf Schneider – Developer and Agile Coach https://ulf.codes Thu, 09 Apr 2020 11:38:59 +0000 Thu, 09 Apr 2020 11:38:59 +0000 Jekyll v3.8.5 Website Accessibility got Worse <p>Dave Rupert made me aware with his <a href="https://twitter.com/davatron5000/status/1247179071890640896">tweet</a>:</p> <blockquote> <p>The average website accessibility got worse during the last twelve months!</p> </blockquote> <p>This is according to the <a href="https://webaim.org/projects/million/">WebAIM annual accessibility analysis</a> of a list of one million homepages. <a href="https://webaim.org/about/">WebAIM</a>, which stands for Web Accessibility In Mind, is a non-profit organization based at the <a href="https://www.cpd.usu.edu/">Center for Persons with Disabilities</a> of the Utah State University.</p> <p>I quote some lowlights of the report as mentioned on their <a href="https://webaim.org/blog/webaim-million-one-year-update/">summary page</a>:</p> <ul> <li>Detectable WCAG failure rate rose from 97.8% to 98.1%.</li> <li>Average number of detectable errors per page was 60.9, a 2.1% increase from 2019.</li> <li>Home page complexity (number of elements per page) rose 10.4% in 12 months, from an average of 782 elements per page to 864.</li> <li>On average, home pages had 36 distinct instances of low-contrast text.</li> <li>31.3% of all home page images (12 per page on average) had missing alternative text.</li> <li>56% of the 3.4 million form inputs identified were unlabeled.</li> <li>There were significant differences in the number of errors based on the content category of home pages. News, weather, and information sites, for example, had twice as many errors as governmental sites.</li> </ul> <p>WebAIM provides a <a href="https://wave.webaim.org">Web Accessibility Evaluation Tool (WAVE)</a>, which is <em>“… a suite of evaluation tools that helps authors make their web content more accessible to individuals with disabilities. WAVE can identify many accessibility and Web Content Accessibility Guideline (WCAG) errors, but also facilitates human evaluation of web content.”</em></p> <p>I immediately <a href="https://wave.webaim.org/report#/https://ulf.codes/">checked my site</a> by using the tool and got hints for improvements.</p> <p>The accessibility situation also seems to resonate with others. For example, Ethan Marcotte explains his approach of writing an <a href="https://ethanmarcotte.com/wrote/an-accessibility-statement/">Accessibility Statement</a> for his site.</p> <p>I like the idea of writing an accessibility statement. I want to focus on accessibility. Writing the statement is an excellent way of making me conscious, and to set a level to reach.</p> Thu, 09 Apr 2020 00:00:00 +0000 https://ulf.codes/journal/website-accessibility-got-worse/ https://ulf.codes/journal/website-accessibility-got-worse/journal Progressive Web Apps – Where Do I Begin? Aaron Gustafson <p><a href="https://aneventapart.com/news/post/progressive-web-apps-where-do-i-begin-aea-video">An Event Apart Video</a></p> Sat, 04 Apr 2020 00:00:00 +0000 https://ulf.codes/reading/pwa-where-do-i-begin/ https://ulf.codes/reading/pwa-where-do-i-begin/reading Weeknotes 14 <ul> <li>Max Böck published a boilerplate <a href="https://mxb.dev/blog/emergency-website-kit/">Emergency Website Kit</a>, which, especially these days, aims to provide a quick way to publish critical information with a single HTTP request. The technique has the ability to handle sudden load spikes with maximum resilience.</li> <li>The complete <a href="https://aneventapart.com/news/post/the-complete-aea-dc-2019-now-online">An Event Apart Washington DC 2019 Sessions</a> are available online. That´s quite something to study.</li> <li>I´ve learned that there is a <code>&lt;time&gt;</code> tag in HTML which <s>can</s> should be used for dates and time to improve semantic HTML.</li> <li>A compelling talk from Aaron Gustafson: <a href="https://aneventapart.com/news/post/progressive-web-apps-where-do-i-begin-aea-video">Progressive Web Apps: Where Do I Begin?</a> It´s not mainly about the Service Worker. Aaron is pointing out that a Progressive Web App aims to enhance <em>– or progress –</em> an already great experience of a website with performance, less network reliance, offline capabilities, and engagement. It´s a chain of: focusing on what matters most for a particular web page to create a great core experience (again, <a href="https://justinjackson.ca/words.html">start with words</a>); writing semantic markup to support the core experience; designing with CSS to support the core experience; and finally using JavaScript to support the core experience.</li> <li><a href="https://www.pwastats.com">PWA Stats</a> is a community-driven list of stats and news related to Progressive Web Apps.</li> <li>Aaron Shekey, Stack Overflow’s principal product designer on design systems, explains how the new <a href="https://stackoverflow.blog/2020/03/31/building-dark-mode-on-stack-overflow/">dark mode</a> of Stack Overflow has been realized.</li> <li><a href="https://stackoverflow.design">Stacks</a> is the design system of Stack Overflow.</li> <li>A beautiful <a href="https://typespecimens.io">collection of typespecimens</a>, curated by John D. Jameson.</li> <li>I have added a search function to my static <a href="https://jekyllrb.com">Jekyll</a>-driven site. It´s a client-side search powered by <a href="https://lunrjs.com">Lunr</a>. Currently the search index for the entire website is built on the client with the first query a user kicks off. This is something that could be improved for the future. But still I´m happy with that thing for now.</li> </ul> <figure><figcaption>Drawing: <a https://ulf.codesemil-drawing/snakes-with-poison-dots/">Snakes with Poison Dots</a>, by Emil on April 3rd, 2020</figcaption></figure> Sat, 04 Apr 2020 00:00:00 +0000 https://ulf.codes/journal/2020-Week-14/ https://ulf.codes/journal/2020-Week-14/journal An RSS feed for GitHub Pages <p>RSS is a good thing. It simplifies to overview information that is produced by potentially many different sources. If someone has an RSS feed on her blog, you can easily subscribe to that feed and have all her published contents in your RSS reader – along with the published contents of other creators. There is also a privacy advantage. You don´t have to provide your mail address to subscribe.</p> <p>I´m building my blog with Jekyll, and hosting it via GitHub Pages. Out of the box, Jekyll doesn´t have RSS feed support. One way to publish a feed is to use the <code>jekyll-feed</code> plugin, which is supported by GitHub Pages. You only need to activate it in your <code>_config.yml</code>:</p> <figure> <figcaption>_config.yml</figcaption> <pre>plugins: – jekyll-feed</pre> </figure> <p>Once Jekyll rebuilds your site with the plugin activated, your RSS feed is available under the URL path <code>/feed.xml/</code>.</p> <h2 id="limitations-of-jekyll-feed">Limitations of jekyll-feed</h2> <p>However, <code>jekyll-feed</code> has some limitations:</p> <ul> <li>It makes all pages and posts available in your feed. You cannot exclude anything, or have different feeds, like for links, a reading list, and maybe your journal.</li> <li>Even posts that have a front matter setting of <code>published: no</code> are immediately visible in your feed.</li> <li>I´m referencing things inside of my blog with relative URLs. E.g., <code>/tools</code>, or <code>/images/we-are-riding-the-bullitt.jpg</code>. Those relative links remain so in your feed. But a relative link doesn´t work inside of an RSS reader, which means an image is not displayed or a link to an article is not functioning. In the RSS reader, you need absolute URLs.</li> </ul> <h2 id="my-own-feed-generator">My own feed generator</h2> <p>To overcome those limitations, I decided not to use <code>jekyll-feed</code> and instead write my own tiny RSS generator. My generator is publishing posts and no pages. Here is what you have to do to use it:</p> <p>For each feed you want to publish, you have to create a markdown file inside of the <code>_pages</code> folder – for example, a feed with the name <code>/feed.rss</code> that publishes the categories <em>thoughts, tools, reading, and journal</em> is represented by a file <code>feed.md</code> with the following front matter contents:</p> <figure> <figcaption>_pages/feed.md</figcaption> <pre>--- layout: postfeed permalink: /feed.xml/ categories: [thoughts, tools, reading, journal] ---</pre> </figure> <p>The address of the published feed, <code>/feed.xml/</code> in this case, doesn´t need to correspond to the name of the feed definition file, <code>feed.md</code> in our example. You define the feed address with the <code>permalink</code> setting inside of the feed definition file.</p> <p>You can have multiple feed definition files with different content filters and subsequently different feed addresses.</p> <p>The filtering of posts is not only working for categories. You can also filter for tags. The following feed definition is valid:</p> <figure> <figcaption>_pages/feed.md</figcaption> <pre>--- layout: postfeed permalink: /feed.xml/ tags: [thoughts, tools, reading, journal] ---</pre> </figure> <p>A logical OR filter combination of categories and tags is in the form:</p> <figure> <figcaption>_pages/feed.md</figcaption> <pre>--- layout: postfeed permalink: /feed.xml/ categories: [tools] tags: [reading, journal] ---</pre> </figure> <p>In the above <code>feed.md</code> file, a layout named <code>postfeed</code> is referenced. The layout file needs to be available under the name <code>postfeed.html</code> in the <code>_layouts</code> folder. The content of <code>postfeed.html</code> is the tiny programm that creates the feed. It is this:</p> <figcaption class="mrt-1">_layouts/postfeed.html</figcaption> <pre class="breakout"><code>&lt;?xml version="1.0" encoding="UTF-8" ?&gt; &lt;rss version="2.0"&gt; &lt;channel&gt; &lt;title&gt;{{- site.title -}}&lt;/title&gt; &lt;description&gt;&lt;/description&gt; &lt;link&gt;{{- site.url -}}{{- site.baseurl -}}&lt;/link&gt; &lt;pubDate&gt;{{ site.time | date_to_rfc822 }}&lt;/pubDate&gt; &lt;lastBuildDate&gt;{{- site.time | date_to_rfc822 -}}&lt;/lastBuildDate&gt; &lt;generator&gt;Jekyll v{{- jekyll.version -}}&lt;/generator&gt; {%- assign imageUrl = "src=&amp;quot;" -%} {%- assign imageUrl = imageUrl | append: site.url -%} {%- assign imageUrl = imageUrl | append: site.baseurl -%} {%- assign imageUrl = imageUrl | append: "/" -%} {%- assign posturl = "href=&amp;quot;" -%} {%- assign postUrl = postUrl | append: site.url -%} {%- assign posturl = postUrl | append: site.baseurl -%} {%- assign posturl = postUrl | append: "/" -%} {%- assign pageMeta = "" | split: "" -%} {%- assign pageMeta = pageMeta | push: page.tags -%} {%- assign pageMeta = pageMeta | push: page.categories -%} {%- assign pageMeta = pageMeta | compact | uniq -%} {%- for p in site.posts -%} {%- for meta in pageMeta -%} {%- if p.published != false -%} {%- if meta == "." or p.tags contains meta or p.categories contains meta -%} &lt;item&gt; &lt;title&gt;{{ p.title | xml_escape }}&lt;/title&gt; &lt;author&gt;{{ p.author }}&lt;/author&gt; &lt;description&gt; {%- if p.subtitle -%}&amp;lt;p&amp;gt;{{- p.subtitle -}}&amp;lt;/p&amp;gt;{%- endif -%} {{- p.content | xml_escape | replace: "src=&amp;quot;/",imageUrl | replace: "href=&amp;quot;/",postUrl -}} &lt;/description&gt; &lt;pubDate&gt;{{- p.date | date_to_rfc822 -}}&lt;/pubDate&gt; &lt;link&gt;{{- p.url | prepend: site.baseurl | prepend: site.url -}}&lt;/link&gt; &lt;guid&gt;{{- p.url | prepend: site.baseurl | prepend: site.url -}}&lt;/guid&gt; {%- for tag in p.tags -%} &lt;category&gt;{{- tag | xml_escape -}}&lt;/category&gt; {%- endfor -%} {%- for c in p.categories -%} &lt;category&gt;{{- c | xml_escape -}}&lt;/category&gt; {%- endfor -%} &lt;/item&gt; {%- break -%} {%- endif -%} {%- endif -%} {%- endfor -%} {%- endfor -%} &lt;/channel&gt; &lt;/rss&gt; </code></pre> <p>Just copy the code above, store it inside of <code>_layouts/postfeed.html</code>, and you are ready to use your new RSS feed.</p> Sat, 28 Mar 2020 00:00:00 +0000 https://ulf.codes/journal/an-rss-feed-for-github-pages/ https://ulf.codes/journal/an-rss-feed-for-github-pages/journal Into the Personal-Website-Verse ★ Matthias Ott <p><a href="https://matthiasott.com/articles/into-the-personal-website-verse">Into the Personal-Website-Verse</a> is a plea for personal websites from Matthias Ott. Excellent stuff! Read it!</p> Fri, 27 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/into-the-personal-website-verse/ https://ulf.codes/reading/into-the-personal-website-verse/reading maldekstra 7 Rosa Luxemburg Stiftung <p>Issue #7 is not about climate change, it´s about climate crisis: <a href="https://www.rosalux.de/publikation/id/41869/alle-reden-vom-klima-wir-reden-ueber-klimagerechtigkeit">Alle reden vom Klima. Wir über Klimagerechtigkeit</a>. An entry into the topic can also be found with their dossier <a href="https://www.rosalux.de/dossiers/klimagerechtigkeit">Klimagerechtigkeit</a>.</p> Sun, 22 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/maldekstra-7/ https://ulf.codes/reading/maldekstra-7/reading Weeknotes 13 <ul> <li>Write personal: <a href="https://matthiasott.com/articles/into-the-personal-website-verse">Into the Personal-Website-Verse</a> is a plea for personal websites from Matthias Ott. That gets a ★.</li> <li><a href="https://airbagindustries.com/advice-from-ten-years-of-leading-remote-teams/">Advice from Ten Years of Leading Remote Teams</a> from Greg Storey.</li> <li><a href="https://www.smashingmagazine.com/2019/02/complex-web-tables/">How to architect a complex web table</a>.</li> <li>This week a collection of the best <a href="https://www.rapha.cc/en/en/stories/the-best-of-rapha-films">Rapha films</a></li> <li>I created my own <a https://ulf.codesjournal/an-rss-feed-for-github-pages/">RSS feed generator</a> for GitHub pages.</li> <li>I changed the typeface of this site. Initially I was using <em><a href="https://rsms.me/inter/">Inter</a>,</em> which is a beautiful and elegant modern type that stays in the background. But I felt it is not ideal for longer text. At least, I thought a serif type would be more suitable. I came to <a href="https://www.ibm.com/plex/">IBM Plex Serif</a> and planned to use that for the reading text while keeping Inter for navigation and meta information. After a while I found the two types did not pair very well. Fortunately, Plex is a family with serif, sans-serif, and even mono fonts. The italic style variants, which exist even for the mono font, are remarkably expressive. Therefore I changed everything to Plex, and now, after some time looking at it, I think it´s going to work for me. The idea of combining humanity and technology in Plex can be noticed when comparing with Inter, which is elegant to an extent one could name antiseptic, but at least rationalized. Compared to that, here is what IBM is saying about their Plex: <em>When we set out to create a typeface that was unmistakably IBM, our own history was our greatest source of inspiration. IBM has always served as a medium between mankind and machine. Between the natural and the engineered. The emotional and rational. The classic and the cutting-edge. Our most important job is to help humanity and technology move forward together. IBM Plex® brings these relationships to life through letterforms.</em> Did it play I role that I was working 10 years for IBM? Maybe, but their typeface – which has been developed by <a href="https://www.boldmonday.com/custom/ibm/">Bold Monday</a> – can speak for itself.</li> <li>Came across <a href="https://bionic-reading.com/en/en-insight/">Bionic Reading</a> which is a concept to format text this way: <strong>Wi</strong>th <strong>Bi</strong>onic <strong>Read</strong>ing <strong>y</strong>ou <strong>r</strong>ead <strong>tex</strong>ts <strong>wi</strong>th <strong>mo</strong>re <strong>foc</strong>us, <strong>aware</strong>ness, <strong>a</strong>nd <strong>sustain</strong>ability. <em>“Bionic Reading wants to revolutionize reading. Our mission is: “A higher dimension of reading.” The eye is guided through text much more effectively with the aid of typographic highlights – thus creating a completely new reading experience.”</em> I´m only wondering, their landing page doesn´t use the bionic reading mode.</li> </ul> Sun, 22 Mar 2020 00:00:00 +0000 https://ulf.codes/journal/2020-week-13/ https://ulf.codes/journal/2020-week-13/journal Weeknotes 12 <ul> <li>Emil pictured the <a https://ulf.codesemil-drawing/emil-pictured-the-coronavirus">virus</a>.</li> <li>I get the case counts from The Johns Hopkins <a href="https://coronavirus.jhu.edu">Coronavirus Resource Center</a>. At the end of this week we are counting 22.000 infected people in Germany, 84 people died. Worldwide, we have 307.000 people infected and 13.049 people died.</li> <li>The Washington Post: <a href="https://www.washingtonpost.com/graphics/2020/world/corona-simulator/">How outbreaks like Coronavirus spread exponentially, and how to “flatten the curve”</a> by Harry Stevens. A very good explanation with comprehensive simulations.</li> <li><a href="http://gabgoh.github.io/COVID/index.html">Epidemic Calculator</a>.</li> <li>A set of free <a href="https://www.iconfinder.com/p/coronavirus-awareness-icons">Coronavirus awareness icons</a> from iconfinder.</li> <li><a href="https://twitter.com/tomjolly/status/1240381892077277187?s=21">How design tells a story</a> from <a href="https://standardregular.com/Andrew-Sondern">Andrew Sondern</a>, Art Director of The New York Times.</li> <li>Another great page: <a href="https://paulliebtpaula.de/ueber-uns/">Paul liebt Paula</a>. I found it on my chase for Lightroom presets, because during this week I discovered that unfortunately <a href="https://vsco.co">VSCO</a> is not in the Lightroom Preset Business anymore.</li> <li>Alternatives for VSCO: <a href="https://hafenliebe.education/presets/">Hafenliebe Presets</a> by Björn Lexius. I like it that Björn has only a limited number of color and bw presets which are to be meant as a starting point for further adjustment. Björn´s presets are currently my favourite. More alternatives are <a href="https://reallyniceimages.com">RNI</a>, and maybe <a href="https://paulliebtpaula.de/presets/">Paul liebt Paula</a>.</li> <li>Debugging CSS with <code>* {outline: 1px solid red;}</code> is better than setting <code>* {border: 1px solid red;}</code>, because outline doesn´t affect the box model!</li> </ul> <figure><figcaption>Drawing made by Emil on March 18th, 2020</figcaption></figure> Sun, 22 Mar 2020 00:00:00 +0000 https://ulf.codes/journal/2020-Week-12/ https://ulf.codes/journal/2020-Week-12/journal Type <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" https://ulf.codescss/compose.css"> <meta name="viewport" content="width=device-width initial-scale=1"> <title>Type</title> </head> <style> :root { --heading-text-transform: none; --mrt-h2: none; --color-step-factor: 0.22; } </style> <body> <div class="bg-base-background breakout-wide x-12 mry-2 gpy-2 gpx min-vh-100"> <div class="md:xx-6 bg-neutral-4 pdx"> <style> .sans { font-family: sans-serif; } .sans h2 { font-family: sans-serif; } .sans .meta { font-family: sans-serif; } .sans code { font-family: monospace; } </style> <label class="meta mry block primary-d2">Sans-serif</label> <div class="sans mxw-rg"> <ul class="reset inline-block meta small mry-0"> <li class="inline-block mrr">Navigation A</li> <li class="inline-block mrr">Navigation B</li> <li class="inline-block">Navigation C</li> </ul> <h2>One morning, when Gregor Samsa woke</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, <i>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</i> The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> </p>His many legs, <code>pitifully thin compared with the size of the rest of him,</code> waved about helplessly as he looked. What's happened to me? he thought. It wasn't a dream.</p> <p class="meta primary-d2">All fonts are system sans-serif. Monospace is system monospace.</p> </div> </div> <div class="md:xx-6 bg-neutral-4 pdx"> <style> @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap'); .inter { font-family: "Inter"; } .inter h2 { font-family: "Inter"; } .inter .meta { font-family: "Inter"; } .inter code { font-family: monospace; } </style> <label class="meta mry block primary-d2">Inter</label> <div class="inter mxw-rg"> <ul class="reset inline-block meta small mry-0"> <li class="inline-block mrr">Navigation A</li> <li class="inline-block mrr">Navigation B</li> <li class="inline-block">Navigation C</li> </ul> <h2>One morning, when Gregor Samsa woke</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, <i>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</i> The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> </p>His many legs, <code>pitifully thin compared with the size of the rest of him,</code> waved about helplessly as he looked. What's happened to me? he thought. It wasn't a dream.</p> <p class="meta primary-d2">All fonts are Inter. Monospace is system monospace.</p> </div> </div> <div class="md:xx-6 bg-neutral-4 pdx"> <style> @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;600&family=IBM+Plex+Sans:wght@400;600&family=IBM+Plex+Serif:ital,wght@0,400;0,600;1,400;1,600&display=swap'); .plex { font-family: "IBM Plex Serif"; } .plex h2 { font-family: "IBM Plex Sans"; } .plex .meta { font-family: "IBM Plex Sans"; } .plex code { font-family: "IBM Plex Mono"; } </style> <label class="meta mry block primary-d2">IBM Plex</label> <div class="plex mxw-rg"> <ul class="reset inline-block meta small mry-0"> <li class="inline-block mrr">Navigation A</li> <li class="inline-block mrr">Navigation B</li> <li class="inline-block">Navigation C</li> </ul> <h2>One morning, when Gregor Samsa woke</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, <i>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</i> The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> </p>His many legs, <code>pitifully thin compared with the size of the rest of him,</code> waved about helplessly as he looked. What's happened to me? he thought. It wasn't a dream.</p> </div> <p class="meta primary-d2">Navigation, meta and headings are IBM Plex Sans, text is IBM Plex Serif, and monospace is IBM Plex Mono. </p> </div> <div class="md:xx-6 bg-neutral-4 pdx"> <style> @import url('https://fonts.googleapis.com/css2?family=Spectral:ital,wght@0,400;0,600;1,400;1,600&display=swap'); .spectral { font-family: "Spectral"; } .spectral h2 { font-family: sans-serif; } .spectral .meta { font-family: sans-serif; } .spectral code { font-family: monospace; } </style> <label class="meta mry block primary-d2">Spectral and Sans-serif</label> <div class="spectral mxw-rg"> <ul class="reset inline-block meta small mry-0"> <li class="inline-block mrr">Navigation A</li> <li class="inline-block mrr">Navigation B</li> <li class="inline-block">Navigation C</li> </ul> <h2>One morning, when Gregor Samsa woke</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, <i>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</i> The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> </p>His many legs, <code>pitifully thin compared with the size of the rest of him,</code> waved about helplessly as he looked. What's happened to me? he thought. It wasn't a dream.</p> </div> <p class="meta primary-d2">Navigation, meta and headings are system sans-serif, text is Spectral, and monospace is system monospace. </p> </div> <div class="md:xx-6 bg-neutral-4 pdx"> <style> .georgia { font-family: "Georgia"; } .georgia h2 { font-family: sans-serif; } .georgia .meta { font-family: sans-serif; } .georgia code { font-family: monospace; } </style> <label class="meta mry block primary-d2">Georgia and Sans-serif</label> <div class="georgia mxw-rg"> <ul class="reset inline-block meta small mry-0"> <li class="inline-block mrr">Navigation A</li> <li class="inline-block mrr">Navigation B</li> <li class="inline-block">Navigation C</li> </ul> <h2>One morning, when Gregor Samsa woke</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, <i>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</i> The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> </p>His many legs, <code>pitifully thin compared with the size of the rest of him,</code> waved about helplessly as he looked. What's happened to me? he thought. It wasn't a dream.</p> </div> <p class="meta primary-d2">Navigation, meta and headings are system sans-serif, text is Georgia, and monospace is system monospace. </p> </div> </div> </body> </html> Sat, 21 Mar 2020 00:00:00 +0000 https://ulf.codes/experiments/type/ https://ulf.codes/experiments/type/experiments How to flatten the curve Harry Stevens <p>The Washington Post: <a href="https://www.washingtonpost.com/graphics/2020/world/corona-simulator/">How outbreaks like Coronavirus spread exponentially, and how to “flatten the curve”</a>.</p> Fri, 20 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/how-to-flatten-the-curve/ https://ulf.codes/reading/how-to-flatten-the-curve/reading This is a web page ★ Justin Jackson <figure><i>At its heart, web design should be about words. Words don't come after the design is done. Words are the beginning, the core, the focus.</i></figure> <p>Excellent. Start with words: <a href="https://justinjackson.ca/words.html">This is a web page</a></p> Tue, 10 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/this-is-a-web-page/ https://ulf.codes/reading/this-is-a-web-page/reading The Birth of Inter Rasmus Andersson and Carmel DeAmicis <p>In “<a href="https://www.figma.com/blog/the-birth-of-inter/">The Birth of Inter</a>” <a href="https://rsms.me">Rasmus Andersson</a> is explaining his (work)flow and tool usage while developing <a href="https://rsms.me/inter/">Inter</a>, a beautiful sans-serif typeface designed for reading text on screens. It is now being used by <a href="https://github.com">GitHub</a>, <a href="https://mozilla.design">Mozilla</a>, and <a href="http://figma.com">Figma</a>, of course. It is open, you can get it from <a href="https://fonts.google.com/specimen/Inter">Google Fonts</a>.</p> Tue, 10 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/the-birth-of-inter/ https://ulf.codes/reading/the-birth-of-inter/reading Weeknotes 11 <ul> <li>This guy <a href="https://jackmcdade.com/">Jack McDade</a> knows how to design a web page. Jack made <a href="https://justinjackson.ca">Justin Jackson´s page</a>, which I think is an exceptional piece of work. Wow. Jack is also working on a <a href="https://radicaldesigncourse.com">radical design course</a>. What could be the name of the style – <em>delicate brutalism?</em></li> <li>Reading Jonathan Snook´s take on a <a href="https://snook.ca/archives/html_and_css/playing-with-css-grid">magazine grid</a>. Jonathan is pointing out himself that popping out random articles in bigger size might irritate users and I have the same concern. I think all sizes and layout should have a meaning.</li> <li>Keir Watson is describing his process to produce a <a href="https://css-tricks.com/responsive-grid-magazine-layout-in-just-20-lines-of-css/">magazine grid</a> with similar properties in incredible detail on CSS Tricks. In fact his CSS grid code does a lot of things in an excellent way while it is only 20 lines long. His explanation however, is multi-page long.</li> <li>Andy Bell describes a technique to <a href="https://piccalil.li/tutorial/creating-a-full-bleed-css-utility/">break out of the mould of your fixed-width container to create visual interest</a>.</li> <li>I learned there are <a href="https://css-tricks.com/almanac/properties/f/font/#article-header-id-1">keywords for defining system fonts</a> in CSS, e.g. <code>caption</code>, <code>menu</code>, and <code>message-box</code>.</li> <li><a href="https://11ty.dev">11ty</a>, <a href="https://www.netlify.com">Netlify</a> and probably <a href="https://developers.google.com/web/tools/workbox">Workbox</a> could be a combination to be used for a nice blog rebuild project, which would eventually turn into a PWA. People seem to be satisfied with 11ty+Netlify.</li> <li>Because of the Coronavirus many people are staying away from the office now. Working from home. Not travelling anymore. Change in behavior and perception. I was talking to Petr, a colleague from Czech Republic, and he told me it´s not allowed to cross the country borders for 3 months from now and schools are closed for 2 months. In Germany schools will be closed for 5 weeks at least. Public events are cancelled, people are doing hamster purchase. Slowly it´s getting scary, though personally I don´t know anyone being infected. I realize that our way of living is not for granted. I´m getting reminded to the book “Blindness” from José Saramago, where a city is hit by an epidemic “white blindness”. A book I enjoyed reading. “The Plague” from Albert Camus could also be something to read again – I think I´ve done it 35 years ago.</li> </ul> Mon, 09 Mar 2020 00:00:00 +0000 https://ulf.codes/journal/2020-Week-11/ https://ulf.codes/journal/2020-Week-11/journal Weeknotes 10 <ul> <li>Watched <a href="https://vimeo.com/ondemand/thereabouts3">Thereabouts 3: Discovering Colombia</a> again. It´s the best of the series. I can recommend this film for anyone who is into cycling.</li> <li>Restarted my sports routine after two weeks of sickness. Next goal is the <a href="https://www.paderborner-osterlauf.de">half marathon in Paderborn</a> at the 11th of April. I hope I stay healthy until then and can do something to improve my shape – it´s necessary :-).</li> <li>Beautiful page from Oslo-based <a href="https://fossheim.io">Sarah Fossheim</a>. An incredible piece of work to create a <a href="https://fossheim.io/writing/posts/css-polaroid-camera/">Polaroid camera with CSS gradients only</a>. Probably more useful for my daily work is her article <a href="https://fossheim.io/writing/posts/accessible-dataviz-design/">Designing accessible data visualizations</a>. Overall, I´m impressed.</li> <li><a href="https://alistapart.com/article/priority-guides-a-content-first-alternative-to-wireframes/">Priority Guides</a>, as a content-first alternative to wireframes, is a concept that makes sense to me. Advantages over wireframes, as stated in the <em>list apart</em> article: Priority guides are suitable for responsive design, the process is content first, you do not waste time with aesthetics and layout, visual designer creativity is facilitated, a priority guide is similar to html.</li> <li>After a discussion with one of our project managers from Mexico I watched <a href="https://www.ted.com/talks/richard_wilkinson_how_economic_inequality_harms_societies?utm_campaign=tedspread&amp;utm_medium=referral&amp;utm_source=tedcomshare">Richard Wilkinson: How economic inequality harms societies</a> again. It´s stunning to me how Richard can make the point that our lives suffer – also the lives of the wealthy – if we allow too much of inequality in our societies. Recommended with a ★.</li> <li>How great is the <a href="https://www.halfarsedagilemanifesto.org">Manifesto for Half-Arsed Agile Software Development</a> :-). Unfortunately a reality in many cases.</li> </ul> Mon, 02 Mar 2020 00:00:00 +0000 https://ulf.codes/journal/2020-Week-10/ https://ulf.codes/journal/2020-Week-10/journal The Shape of Design Frank Chimero <figure> <p>From the book:</p> <i> <p>… Painting’s near and far states are akin to How and Why: the artist, when close to the canvas, is asking How questions related to craft; when he steps back, he raises Why questions concerned with the whole of the work and its purpose. Near and Far may be rephrased as Craft and Analysis, which describe the kinds of questions the artist asks while in each mode. This relationship can be restated in many different ways, each addressing a necessary balance: How and Why, Near and Far, Making and Thinking, Execution and Strategy, Craft and Analysis …</p> <p>… How enables, but Why motivates, and the space between the two could be described by the gap of enthusiasm between simply understanding phonics and reading a book that one identifies with and loves. </p> <p>… The first step of any process should be to define the objectives of the work with Why-based questions. The second step, however, should be to put those objectives in a drawer. Objectives guide the process toward an effective end, but they don’t do much to help one get going. In fact, the weight of the objectives can crush the seeds of thought necessary to begin down an adventurous path.</p> <p>The creative process, like a good story, needs to start with a great leap of lightness, and that is only attainable through a suspension of disbelief. The objectives shouldn’t be ignored forever, but they should be defined ahead of time, set aside, and then deployed at the appropriate moment so that we may be audacious with our ideas.</p> <p>… judgment is an important part of the creative process, but when improvising, self-criticism and evaluation from others must be avoided in order to let ideas develop from their delicate state. Criticism has a crucial role in the creative process, but its rigor should match the heartiness of the ideas, which become stronger as they develop. The more real an idea becomes, the less suspension of disbelief is required, and the more criticism it should withstand. But all ideas, both good and bad, start young and fragile.</p> <p>… The way one creatively wanders is through improvisation. […] The first maxim of improv is “Yes and….” This rule is easy to understand, but like most cardinal virtues, it is much more difficult to execute than to grasp. </p> <p>… Limitations narrow a big process into a smaller, more understandable space to explore. It’s the difference between swimming in a pool and being dropped off in the middle of the ocean with no land in sight.</p> <p>… My body and mind are linked. This is hardly a ground-breaking discovery, but for the longest time, it was a bit of knowledge that never changed my behavior. If my mind needed to wander to think about a project, I’d typically sit in a chair, furrow my brow, sip my coffee, and scribble a few things into my sketchbook. That’s no good, though: if the mind needs to wander, best let the body do the same. A short walk is more effective in coming up with an idea than pouring all the coffee in the world down your gullet.</p> <p>… All design work seems to have three common traits: there is a message to the work, the tone of that message, and the format that the work takes. Successful design has all three elements working in co-dependence to achieve a whole greater than the sum of the individual parts.</p> <p>… Evolution occurs one step at a time, and the size of each step is limited: nature must first create the cells in leaves that can capture the energy of the sun before it can produce a flower.</p> <p>… our collective ideas advance with the same limitations.</p> <p>… Our magicians—our Henry Fords, our Billie Holidays, our Gutenbergs, Disneys, and Marie Curies—do not stand on the inside of what is possible and push; they imagine what is just outside of what we deem possible and pull us towards their vision of what is better. </p> <p>… the primary position in conversation is the one listening rather than the speaker …</p> <p>… Web design connects the user to the site’s owner and offers a venue for the connection to develop and grow.</p> <p>… The qualities of design consistently change, because there is a wide variety of characteristics in what design connects. It means that design lives in the borderlands – it connects, but it does not anchor. </p> <p>… Design can speak the tongue of art with the force of commerce. The products of design maneuver in the streets of the city where people live, rather than the halls of a museum where they must be visitors. There needn’t be the pressure of artistic credibility or commercial profitability always present, which means that the work of the designer can go further in shaping culture than a traditional piece of art, and make money in a way that has more soul and spill-over benefits than straight commerce.</p> <p>… It means that the products of design are not autonomous objects, but are creations that bridge in-between spaces to provide a way toward an intended outcome. The design must be transformative for it to be successful. It must take us somewhere. Airports and train stations are other examples of non-autonomous creations that exist as in-between spaces, because they have been built out of our desire to go somewhere else. Even cathedrals could be considered spaces of transit, because they seek to connect the physical world with the spiritual realm. Design is akin to these places in that their usefulness is defined by the consequences of the connections they facilitate. A train station that doesn’t create a lust for exploration is flawed, just as a cathedral that doesn’t inspire awe is a failure.</p> <p>… The necessities and influence of subject and context, whether in portraiture, installation, or design, take time to unfold. It is the designer’s job to figure out a way to have a problem show its actual self so that he can respond to the truth that has emerged. Getting to know a problem is a bit like getting to know a person: it’s a gradual process that requires patience, and there is no state of completion. You can never know the full of a problem, because there is never comprehensive information available. You have to simply draw the line somewhere and make up the rest as you go along.</p> </i> </figure> <p>The book is available online: <a href="https://shapeofdesignbook.com">The Shape of Design</a></p> Sun, 01 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/the-shape-of-design/ https://ulf.codes/reading/the-shape-of-design/reading It Doesn't Have to Be Crazy at Work Jason Fried and David Heinemeier Hansson <figure> <p>From the book:</p> <i> <p>Chaos should not be the natural state at work. Anxiety isn’t a prerequisite for progress. Sitting in meetings all day isn’t required for success. These are all perversions of work — side effects of broken models and follow-the-lemming-off-the-cliff worst practices. Step aside and let the suckers jump. Calm is profitability. Calm is protecting people’s time and attention. Calm is reasonable expectations. Calm is about 40 hours of work a week. Calm is ample time off. Calm is smaller. Calm is a visible horizon. Calm is meetings as a last resort. Calm is contextual communication. Calm is asynchronous first, real-time second. Calm is more independence, less interdependence. Calm is about sustainable practices that can run for the long-term.</p> </i> </figure> <p><a href="https://basecamp.com/books/calm">Book Landing Page</a></p> Sun, 01 Mar 2020 00:00:00 +0000 https://ulf.codes/reading/it-does-not-have-to-be-crazy/ https://ulf.codes/reading/it-does-not-have-to-be-crazy/reading Weeknotes 9 <ul> <li>Signed <a href="https://assange-helfen.de/en">assange-helfen</a>. A state has been caught in a war crime and for that reason the state takes revenge on the person who helped to reveal everything. Making <a href="https://www.nytimes.com/video/multimedia/1248069533084/collateral-murder.html">Collateral Murder</a> public was important. Protecting whistleblowers is important.</li> <li>Learned about <a href="https://css-tricks.com/fixed-headers-and-jump-links-the-solution-is-scroll-margin-top/">scroll-margin-top</a> from CSS Tricks.</li> <li>Found two designers whose work really resonates with me. There is a lot to learn from <a href="https://frankchimero.com">Frank Chimero</a> and <a href="http://markboulton.co.uk/">Mark Boulton</a>.</li> <li>Published <a https://ulf.codescompose">Compose CSS v3.0.0</a>.</li> <li>Interesting: <a href="https://fabianburghardt.de/webolution/">The Evolution of Web Design</a>.</li> <li>Have to evaluate <a href="https://accessible-colors.com">accessible colors</a> for anything with colors.</li> <li>Installed <a href="http://colorslurp.com">ColorSlurp</a> color picker and like the tool.</li> <li>Read about how Jonnie Hallmann redesigned his website <a href="https://destroytoday.com">destroytoday</a>. He describes in his <a href="https://destroytoday.com/blog">Blog</a> that he used Nuxt and Contentful. That´s an interesting choice because I like Vue and couldn´t become a friend of React so far. I´m carrying the idea of running my blog as a PWA for some time now – just to learn it. Therefore I will probably borrow ideas from Jonnie.</li> <li>I like the perceived simplicity of Robin Rendle´s <a href="https://www.robinrendle.com/essays/systems-mistakes-and-the-sea">essay design</a>. However, I´m missing a navigation back to his page.</li> <li>Had to read about collapsing margins again and found the <a href="https://bitsofco.de/collapsible-margins/">explanation from Ire Aderinokun</a> very beneficial.</li> <li>“It´s not fun anymore…” – Watched a down to earth <a href="https://youtu.be/laMBEjxlst8">Paul Tierney running the Wainwrights</a>. Beautiful landscape, comradery, achievement, and suffering!</li> </ul> Mon, 24 Feb 2020 00:00:00 +0000 https://ulf.codes/journal/2020-Week-9/ https://ulf.codes/journal/2020-Week-9/journal Active Toc <style> #toc a { color: unset; text-decoration: unset; display: block; margin-top: var(--space); } #toc .is-active { color: var(--accent-one) } #toc .is-visible { color: var(--accent-two); } #toc .is-highlight { font-weight: bold; color: var(--primary); } #toc { position: fixed; width: 9rem; top: 0; left: 0; font-weight: normal; line-height: 1rem; padding-left: 1rem; } .content { margin-left: 9rem; } h2 { scroll-margin-top: var(--space-1); } </style> <div id="toc" class="meta"> <a https://ulf.codestools" class="mrb-2">ulf.codes</a> <a href="#one-morning">One morning</a> <a href="#he-thought">He thought</a> <a href="#gregor-then">Gregor then</a> <a href="#he-must">He must</a> <a href="#doing-business">Doing business</a> <a href="#he-felt">He felt</a> <a href="#you-ve-got">You´ve got</a> <a href="#if-i">If I</a> <a href="#well">Well</a> <a href="#he-could">He could</a> <a href="#and-even">And even</a> <a href="#his-boss">His boss</a> <a href="#he-lay">He lay</a> <a href="#a-collection">A collection</a> <a href="#however-hard">However hard</a> </div> <div class="breakout-l content pdy-3 "> <h1 class="mrt-0">active-toc</h1> <p class="mrt-1 mrb-4">An <a href="https://www.npmjs.com/package/active-toc">npm package</a> to highlight the entries of your table of contents while scrolling your website. active-toc is leveraging the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API">Intersection Observer API</a>.</p> <hr /> <h2 id="one-morning">One morning</h2> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me?"</p> <h2 id="he-thought">He thought</h2> <p>he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls. A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer.</p> <h2 id="gregor-then">Gregor then</h2> <p>Gregor then turned to look out the window at the dull weather. Drops of rain could be heard hitting the pane, which made him feel quite sad. "How about if I sleep a little bit longer and forget all this nonsense", he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state couldn't get into that position. However hard he threw himself onto his right, he always rolled back to where he was.</p> <h2 id="he-must">He must</h2> <p>He must have tried it a hundred times, shut his eyes so that he wouldn't have to look at the floundering legs, and only stopped when he began to feel a mild, dull pain there that he had never felt before. "Oh, God", he thought, "what a strenuous career it is that I've chosen! Travelling day in and day out.</p> <h2 id="doing-business">Doing business</h2> <p>Doing business like this takes much more effort than doing your own business at home, and on top of that there's the curse of travelling, worries about making train connections, bad and irregular food, contact with different people all the time so that you can never get to know anyone or become friendly with them. It can all go to Hell!"</p> <h2 id="he-felt">He felt</h2> <p>He felt a slight itch up on his belly; pushed himself slowly up on his back towards the headboard so that he could lift his head better; found where the itch was, and saw that it was covered with lots of little white spots which he didn't know what to make of; and when he tried to feel the place with one of his legs he drew it quickly back because as soon as he touched it he was overcome by a cold shudder. He slid back into his former position. "Getting up early all the time", he thought, "it makes you stupid.</p> <h2 id="you-ve-got">You´ve got</h2> <p>You've got to get enough sleep. Other travelling salesmen live a life of luxury. For instance, whenever I go back to the guest house during the morning to copy out the contract, these gentlemen are always still sitting there eating their breakfasts. I ought to just try that with my boss; I'd get kicked out on the spot. But who knows, maybe that would be the best thing for me.</p> <h2 id="if-i">If I</h2> <p>If I didn't have my parents to think about I'd have given in my notice a long time ago, I'd have gone up to the boss and told him just what I think, tell him everything I would, let him know just what I feel. He'd fall right off his desk! And it's a funny sort of business to be sitting up there at your desk, talking down at your subordinates from up there, especially when you have to go right up close because the boss is hard of hearing.</p> <h2 id="well">Well</h2> <p>Well, there's still some hope; once I've got the money together to pay off my parents' debt to him – another five or six years I suppose – that's definitely what I'll do. That's when I'll make the big change. First of all though, I've got to get up, my train leaves at five. " And he looked over at the alarm clock, ticking on the chest of drawers. "God in Heaven! " he thought. It was half past six and the hands were quietly moving forwards, it was even later than half past, more like quarter to seven. Had the alarm clock not rung?</p> <h2 id="he-could">He could</h2> <p>He could see from the bed that it had been set for four o'clock as it should have been; it certainly must have rung. Yes, but was it possible to quietly sleep through that furniture-rattling noise? True, he had not slept peacefully, but probably all the more deeply because of that. What should he do now? The next train went at seven; if he were to catch that he would have to rush like mad and the collection of samples was still not packed, and he did not at all feel particularly fresh and lively.</p> <h2 id="and-even">And even</h2> <p>And even if he did catch the train he would not avoid his boss's anger as the office assistant would have been there to see the five o'clock train go, he would have put in his report about Gregor's not being there a long time ago. The office assistant was the boss's man, spineless, and with no understanding. What about if he reported sick? But that would be extremely strained and suspicious as in fifteen years of service Gregor had never once yet been ill.</p> <h2 id="his-boss">His boss</h2> <p>His boss would certainly come round with the doctor from the medical insurance company, accuse his parents of having a lazy son, and accept the doctor's recommendation not to make any claim as the doctor believed that no-one was ever ill but that many were workshy. And what's more, would he have been entirely wrong in this case? Gregor did in fact, apart from excessive sleepiness after sleeping for so long, feel completely well and even felt much hungrier than usual. One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <h2 id="he-lay">He lay</h2> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me? " he thought. It wasn't a dream. His room, a proper human room although a little too small, lay peacefully between its four familiar walls.</p> <h2 id="a-collection">A collection</h2> <p>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather. Drops of rain could be heard hitting the pane, which made him feel quite sad. "How about if I sleep a little bit longer and forget all this nonsense", he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state couldn't get into that position.</p> <h2 id="however-hard">However hard</h2> <p>However hard he threw himself onto his right, he always rolled back to where he was. He must have tried it a hundred times, shut his eyes so that he wouldn't have to look at the floundering legs, and only stopped when he began to feel a mild, dull pain there that he had never felt before. "Oh, God", he thought, "what a strenuous career it is that I've chosen! Travelling day in and day out. Doing business like this takes much more effort than doing your own business at home, and on top of that there's the curse of travelling, worries about making train connections, bad and irregular food, contact with different people all the time so that you can never get to know anyone or become friendly with them. It can all go to Hell! " He felt a slight itch up on his belly; pushed himself slowly up on his back towards the headboard so that he could lift his head better; found where the itch was, and saw that it was covered with lots of little white spots which he didn't know what to make of; and when he tried to feel the place with one of his legs he drew it quickly back because as soon as he touched it he was overcome by a cold</p> </div> <script src="https://ulf.codes/r/active-toc.min.js"></script> <script> ActiveToc.init({tocContainer: '#toc'}); </script> Thu, 02 Jan 2020 00:00:00 +0000 https://ulf.codes/tools/active-toc/ https://ulf.codes/tools/active-toc/tools Compose CSS <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" https://ulf.codescss/compose.css"> <meta name="viewport" content="width=device-width initial-scale=1"> <title>COMPOSE CSS</title> </head> <style> .is-highlight { font-weight: bold; } .only-when-dynamic { display: none; } .is-dynamic .only-when-dynamic { display: block; font-weight: normal; } .is-dynamic { border-bottom: var(--space-d2) solid white; } .bookmark a { position: fixed; left: 0; bottom: 0; background: var(--heading-color); color: var(--base-background); padding-left: var(--space); padding-right: var(--space-d2); text-transform: uppercase; visibility: hidden; border-top-right-radius: var(--rounded); } .bookmark a.is-highlight { visibility: visible; } body>h2::before, div>h2::before { content: ""; display: block; background: var(--heading-color); width: var(--space-4); height: var(--space-d1); } :root { --mrt-h2: calc(var(--space-4) * var(--space-factor)); --mrt-h3: var(--space-4); --fs-h1: var(--fs-5); --fs-h2: var(--fs-4); } </style> <body class="bg-primary-3"> <div class="bg-base-background min-vh-100"> <div class="xl"> <div id="top" class="breakout-full bg-neutral-4"> <div class="xl pdt-3 mrb-2"> <div> <h1 class="mr-0 lh fw-700 caps lsp">Compose CSS</h1> <p class="mxw-sm mrt-d1">A composable CSS Toolkit to build fast, maintainable, and responsive websites. </p> </div> <div class="pd mry-d1 xx-3 inline-block bg-black rounded white"><span id="version">v4.4.0</span> </div> </div> <header id="navigation" class="bg-neutral-4 small" style="z-index: 1000;"> <div class="xl md:columns-4 sm:columns-3 columns-2 lh-4 pdy caps small lsp"> <div><a href="#start" class="no-deco">Quickstart</a></div> <div><a href="#notation" class="no-deco">Notation</a></div> <div><a href="#typography" class="no-deco">Typography</a></div> <div><a href="#colors" class="no-deco">Colors</a></div> <div><a href="#white-space" class="no-deco">White Space</a></div> <div><a href="#borders" class="no-deco">Borders</a></div> <div><a href="#tables" class="no-deco">Tables</a></div> <div><a href="#figures" class="no-deco">Figures</a></div> <div><a href="#images" class="no-deco">Images</a></div> <div><a href="#x-layout" class="no-deco">X Layout</a></div> <div><a href="#layout" class="no-deco">Layout</a></div> <div><a href="#columns" class="no-deco">Columns</a></div> <div><a href="#column-grid" class="no-deco">12 Col Grid</a></div> <div><a href="#flexbox" class="no-deco">Flexbox</a></div> <div><a href="#width" class="no-deco">Width</a></div> <div><a href="#height" class="no-deco">Height</a></div> <div><a href="#square" class="no-deco">Square</a></div> <div><a href="#hide" class="no-deco">Hide</a></div> <div><a href="#forms" class="no-deco">Forms</a></div> <div><a https://ulf.codestools" class="no-deco">↰ ulf.codes</a></div><div class="only-when-dynamic"><a href="#top" class="no-deco">↑ Go to top</a></div> </div> <div class="bookmark small"> <a href="#start" class="no-deco">Quickstart</a> <a href="#notation" class="no-deco">Notation</a> <a href="#typography" class="no-deco">Typography</a> <a href="#colors" class="no-deco">Colors</a> <a href="#white-space" class="no-deco">White Space</a> <a href="#borders" class="no-deco">Borders</a> <a href="#tables" class="no-deco">Tables</a> <a href="#figures" class="no-deco">Figures</a> <a href="#images" class="no-deco">Images</a> <a href="#x-layout" class="no-deco">X Layout</a> <a href="#layout" class="no-deco">Layout</a> <a href="#columns" class="no-deco">Columns</a> <a href="#column-grid" class="no-deco">12 Col Grid</a> <a href="#flexbox" class="no-deco">Flexbox</a> <a href="#width" class="no-deco">Width</a> <a href="#height" class="no-deco">Height</a> <a href="#square" class="no-deco">Square</a> <a href="#hide" class="no-deco">Hide</a> <a href="#forms" class="no-deco">Forms</a> </div> </header> </div> <div> <h2 class="pdt-3 mrt-0" id="start">Quickstart</h2> <p>Compose CSS is on <a href="https://github.com/ulfschneider/compose-css">GitHub</a>.</p> <p>Download the <a href="https://raw.githubusercontent.com/ulfschneider/compose-css/master/css/compose.css">Compose CSS</code></a> file and put it into the css folder of your website project. </p> <p>Reference the CSS file in your HTML:</p> <pre class="mid">&lt;link rel="stylesheet" type="text/css" https://ulf.codescss/compose.css"></pre> <p>By then you are ready to use Compose CSS.</p> <p>Another way to use Compose CSS is by adding the <a href="https://www.npmjs.com/package/compose-css">compose-css</a> npm package to your node project. Install with</p> <pre>npm i compose-css</pre> </div> <div> <h2 id="notation">Notation</h2> <p>Throughout this document the following notation is applied:</p> <table> <tr> <td><code>div /div</code></td> <td>HTML tags are indicated by their name. The closing HTML tag is indicated with a prefixed slash. </td> </tr> <tr> <td><code>div/</code></td> <td>The abbreviated form of an opening and closing HTML tag is indicated by the tag name with a trailing slash.</td> </tr> <tr> <td><code>.left</code></td> <td>CSS classes are indicated with a prefixed dot</td> </tr> <tr> <td><code>.left.middle</code></td> <td>The assignment of multiple CSS classes to a single HTML tag, composing, is indicated with a prefixed dot for each CSS class; and there is no white space between classes.</td> </tr> <tr> <td class="no-wrap"><code>i</code>, <code>.i</code>, <code>.italic</code></td> <td>Multiple styling options that produce the same result are indicated by HTML tag names or CSS class names, each one seperated by comma.</td> </tr> </table> </div> <div> <h2 id="typography">Typography</h2> <h3>Elements</h3> <p><span class="mrr">Regular</span> <code>.normal</code></p> <p><a href="#" class="mrr">Link</a> <code>a</code></p> <p><b class="mrr">Bold</b> <code>strong</code>, <code>b</code>, <code>.strong</code>, <code>.bold</code>, <code>.b</code></p> <p><i class="mrr">Italic</i> <code>i</code>, <code>.i</code>, <code>.italic</code></p> <p><span class="normal mrr">Normal</span> <code>.normal</code></p> <p><u class="mrr">Underline</u> <code>u</code>, <code>.underline</code></p> <p><del class="mrr">Deleted</del> <code>del</code>, <code>.del</code></p> <p><span class="mrr caps">Caps</span> <code>.caps, .uppercase</code></p> <p><span class="mrr lowercase">Lowercase</span> <code>.lowercase</code></p> <p><span class="mrr lsp">Letter Spacing</span> <code>.lsp</code></p> <p><mark class="mrr">Highlighted</mark> <code>mark</code>, <code>.mark</code></p> <p><kbd class="mrr">Ctrl+K</kbd> <code>kbd</code>, <code>.kbd</code></p> <p><span class="mrr">Text <sup>superscript</sup></span> <code>sup</code>, <code>.sup</code></p> <p><span class="mrr">Text <sub>subscript</sub></span> <code>sub</code>, <code>.sup</code></p> <p><cite class="mrr">Cite</cite> <code>cite</code>, <code>.cite</code></p> <p><q class="mrr">Quote</q> <code>q, .q, .quote</code></p> <p><em class="mrr">Emphasis</em> <code>em</code>, <code>.em</code></p> <p><s class="strike mrr">Strikethrough</s> <code>s</code>, <code>.s</code>, <code>.strike</code></p> <p><small class="mrr">Small</small> <code>small</code>, <code>.small</code></p> <p><code class="mrr">Code</code> <code>code</code>, <code>.code</code></p> <p><span class="meta mrr">Meta Text</span> <code>.meta</code></p> </div> <div> <h3>Special Cases</h3> <p><a href="#" class="mrr no-deco">A link without text decoration</a> <code>.no-deco</code></p> <p> <div class="block br width-3 height-2 no-wrap mrr">No word wrap at white space</div> <code>.no-wrap</code> </p> <p> <div class="block br width-2 height-4 word-wrap mrr lh">Word wrap anywhere</div> <code>.word-wrap</code> </p> <p> <div class="block br width-3 height-2 truncate mrr">No word wrap at white space</div> <code>.truncate</code> </p> <div class="br"> <hr> </div> <code>hr</code> </div> <div> <h3>Paragraph</h3> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> <p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream.</p> <pre class="mid">p/</pre> </div> <div> <h3>Indented Paragraph</h3> <div class="indent"> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> <p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream.</p> </div> <pre class="mid">div .indent p/ /div p/ .indent p/ .no-indent //remove indentation for this p</pre> </div> <div> <h3>Unordered List</h3> <ul> <li>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </li> <li>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. <ul> <li>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream. </li> <li>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </li> </ul> </li> <li>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. </li> </ul> <pre class="mid">ul li/ /ul</pre> </div> <div> <h3>Indented Unordered List</h3> <ul class="indent"> <li>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </li> <li>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. <ul> <li>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream. </li> <li>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </li> </ul> </li> <li>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. </li> </ul> <pre class="mid">ul .indent li/ /ul</pre> </div> <div> <h3>Ordered List</h3> <ol> <li>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </li> <li>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. <ol> <li>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream. </li> <li>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </li> </ol> </li> <li>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. </li> </ol> <pre class="mid">ol li/ /ol</pre> </div> <div> <h3>Indented Ordered List</h3> <ol class="indent"> <li>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </li> <li>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. <ol> <li>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream. </li> <li>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </li> </ol> </li> <li>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame. </li> </ol> <pre class="mid">ol .indent li/ /ol</pre> </div> <div> <h3>Definition List</h3> <dl> <dt>One morning</dt> <dd>when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</dd> </dl> <dl> <dt>He lay on his armour-like back</dt> <dd>and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</dd> </dl> <dl> <dt>His many legs</dt> <dd>pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream. </dd> </dl> <dl> <dt>His room</dt> <dd>a proper human room although a little too small, lay peacefully between its four familiar walls.</dd> </dl> <pre class="mid">dl dt/ dd/ /dl</pre> </div> <div> <h3>Blockquote</h3> <figure> <blockquote> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections.</p> </blockquote> <figcaption>Franz Kafka, <cite>The Metamorphosis</cite></figcaption> </figure> <pre class="mid">blockquote/ blockquote p/ /blockquote figure blockquote p/ figcaption/ /blockquote /figure</pre> </div> <div> <h3>Writing Mode</h3> <div class="x-12 gpy-2"> <div class="xx-12 sm:xx-4"> <div class="square-4 horizontal-tb bg-neutral-4"> He lay on his armour-like back </div> <code>.horizontal-tb</code> </div> <div class="xx-12 sm:xx-4"> <div class="square-4 vertical-lr bg-neutral-4"> He lay on his armour-like back </div> <code>.vertical-lr</code> </div> <div class="xx-12 sm:xx-4"> <div class="square-4 vertical-rl bg-neutral-4"> He lay on his armour-like back </div> <code>.vertical-rl</code> </div> </div> </div> <h3>Heading Styling</h3> <table> <tr> <td class="baseline pdy-0 right"> <h1 class="mr-0 pd-0">H1</h1> </td> <td class="code baseline pdy-0">h1</td> </tr> <tr> <td class="baseline pdy-0 right"> <h2 class="mr-0 pd-0">H2</h2> </td> <td class="code baseline pdy-0 no-wrap">h2</td> </tr> <tr> <td class="baseline pdy-0 right"> <h3 class="mr-0 pd-0">H3</h3> </td> <td class="code baseline pdy-0">h3</td> </tr> <tr> <td class="baseline pdy-0 right"> <h4 class="mr-0 pd-0">H4</h4> </td> <td class="code baseline pdy-0">h4</td> </tr> <tr> <td class="baseline pdy-0 right"> <h5 class="mr-0 pd-0">H5</h5> </td> <td class="code baseline pdy-0 no-wrap">h5 <small>(1rem)</small></td> </tr> <tr> <td class="baseline pdy-0 right"> <h6 class="mr-0 pd-0">H6</h6> </td> <td class="baseline pdy-0 no-wrap"><code>h6</code></td> </tr> </table> <h3>Heading Sizing</h3> <table> <tr> <td class="h1 baseline pdy-0 right">H1</td> <td class="code baseline pdy-0">.h1</td> </tr> <tr> <td class="h2 baseline pdy-0 right">H2</td> <td class="code baseline pdy-0 no-wrap">.h2</td> </tr> <tr> <td class="h3 baseline pdy-0 right">H3</td> <td class="code baseline pdy-0">.h3</td> </tr> <tr> <td class="h4 baseline pdy-0 right">H4</td> <td class="code baseline pdy-0">.h4</td> </tr> <tr> <td class="h5 baseline pdy-0 right">H5</td> <td class="code baseline pdy-0 no-wrap">.h5 <small>(1rem)</small></td> </tr> <tr> <td class="h6 baseline pdy-0 right">H6</td> <td class="baseline pdy-0 no-wrap"><code>.h6</code></td> </tr> </table> <div> <h3>Font Size</h3> <table> <tr> <td class="fs-d1 baseline pdy-0 right lh pdy-0">Aa</td> <td class="code baseline pdy-0 pdy-0">.fs-d1</td> </tr> <tr> <td class="fs baseline pdy-0 lh right">Aa</td> <td class="baseline pdy-0"><code>.fs</code>, <code>.fs-default</code> <small>(1rem)</small> </td> </tr> <tr> <td class="fs-1 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-1</td> </tr> <tr> <td class="fs-2 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-2</td> </tr> <tr> <td class="fs-3 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-3</td> </tr> <tr> <td class="fs-4 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-4</td> </tr> <tr> <td class="fs-5 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-5</td> </tr> <tr> <td class="fs-6 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-6</td> </tr> <tr> <td class="fs-7 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-7</td> </tr> <tr> <td class="fs-8 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-8</td> </tr> <tr> <td class="fs-9 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-9</td> </tr> <tr> <td class="fs-10 baseline pdy-0 lh right">Aa</td> <td class="code baseline pdy-0">.fs-10</td> </tr> </table> </div> <div> <h3>Line Height</h3> <table> <tr> <td class="lh-d1 brt baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</td> <td class="lh-d1 code baseline pdl pd-0">.lh-d1</td> </tr> <tr> <td class="lh brt baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</td> <td class="lh baseline pdl pd-0"><code>.lh</code> <small>(1em)</small></td> </tr> <tr> <td class="lh-1 brt baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </td> <td class="lh-1 code baseline pdl pd-0">.lh-1</td> </tr> <tr> <td class="lh-2 brt baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</td> <td class="lh-2 code baseline pdl pd-0">.lh-2</td> </tr> <tr> <td class="lh-3 brt baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</td> <td class="lh-3 baseline pdl pd-0"><code class="no-wrap">.lh-3</code>, <code class="no-wrap">.lh-unset</code></td> </tr> <tr> <td class="lh-4 brt m brb baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </td> <td class="lh-4 code baseline pdl pd-0">.lh-4</td> </tr> <tr> <td class="lh-5 brt m brb baseline pd-0">One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. </td> <td class="lh-5 code baseline pdl pd-0">.lh-5</td> </tr> </table> </div> <div> <h3>Responsive Breakpoints</h3> <p>Heading size, font size, and line height can have different sizes based on minimum screen width. Address the different minimum screen sizes with responsive breakpoints, wich are indicated by CSS class prefix values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The size is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The size is applied only if the screen is at least of regular size.</td> </tr> <tr> <td><code>.md:</code></td> <td>The size is applied only if the screen is at least of mid size.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The size is applied only if the screen is at least of large size.</td> </tr> </table> <p>E.g. <code>.lg:fs-1</code>, <code>.md:h1</code>, or <code>.rg:lh-3</code>.</p> <p> A size class without a prefix will be used in case the alternate minimum screen size is not defined.</p> <p class="fs-1 lh-2 rg:fs-2 md:fs-3 lg:fs-4">One morning, when Gregor Samsa woke from troubled dreams </p> <pre class="mid">p/ .fs-1.rg:fs-2.md:fs-3.lg:fs-4</pre> </div> <div> <h3>Font Weight</h3> <table> <tr> <td class="fw-100 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-100</td> </tr> <tr> <td class="fw-200 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-200</td> </tr> <tr> <td class="fw-300 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-300</td> </tr> <tr> <td class="fw-400 fs-4 baseline pdy-0">Aa</td> <td class="baseline pdy-0 no-wrap"><code>.fw-400</code>, <code>.fw-normal</code>, <code>.normal</code> </td> </tr> <tr> <td class="fw-500 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-500</td> </tr> <tr> <td class="fw-600 fs-4 baseline pdy-0">Aa</td> <td class="baseline pdy-0 no-wrap"><code>.fw-600</code>, <code>.bold</code>, <code>bold</code> </td> </tr> <tr> <td class="fw-700 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-700</td> </tr> <tr> <td class="fw-800 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-800</td> </tr> <tr> <td class="fw-900 fs-4 baseline pdy-0">Aa</td> <td class="code baseline pdy-0">.fw-900</td> </tr> </table> </div> <div> <h3>Letter Spacing</h3> <table> <tr> <td class="fs-1 lsp-0 baseline">The quick brown fox</td> <td class="baseline"><code>.lsp-0</code>, <code>.no-lsp</code></td> </tr> <tr> <td class="fs-1 lsp-1 baseline">The quick brown fox</td> <td class="code baseline">.lsp-1</td> </tr> <tr> <td class="fs-1 lsp-2 baseline">The quick brown fox</td> <td class="code baseline">.lsp-2</td> </tr> <tr> <td class="fs-1 lsp-3 baseline">The quick brown fox</td> <td class="code baseline">.lsp-3</td> </tr> <tr> <td class="fs-1 lsp-4 baseline">The quick brown fox</td> <td class="code baseline">.lsp-4</td> </tr> </table> </div> <div> <h3>Numbers</h3> <table> <tr> <td class="fs-2 ft-num-normal baseline">13679.05</td> <td class="baseline"><code>.ft-num-normal</code> <small>(default)</small></td> </tr> <tr> <td class="fs-2 ft-num-tab baseline">13679.05</td> <td class="baseline"><code>.ft-num-tab</code> <small>(default for tables)</small></td> </tr> </table> </div> <div class="breakout"> <h2 id="colors">Colors</h2> <h3>The Color System</h3> <table class="code"> <tr class="center"> <th></th> <th class="normal pdx-0">d5</th> <th class="normal pdx-0">d4</th> <th class="normal pdx-0">d3</th> <th class="normal pdx-0">d2</th> <th class="normal pdx-0">d1</th> <th class="normal pdx-0 brx brw-d4 br-white"></th> <th class="normal pdx-0">1</th> <th class="normal pdx-0">2</th> <th class="normal pdx-0">3</th> <th class="normal pdx-0">4</th> <th class="normal pdx-0">5</th> </tr> <tr> <th class="middle normal">.neutral </th> <td class="bg-neutral-d5 square sm:square-2"></td> <td class="bg-neutral-d4 square sm:square-2"></td> <td class="bg-neutral-d3 square sm:square-2"></td> <td class="bg-neutral-d2 square sm:square-2"></td> <td class="bg-neutral-d1 square sm:square-2"></td> <td class="bg-neutral square sm:square-2 brx brw-d4 br-white"></td> <td class="bg-neutral-1 square sm:square-2"></td> <td class="bg-neutral-2 square sm:square-2"></td> <td class="bg-neutral-3 square sm:square-2"></td> <td class="bg-neutral-4 square sm:square-2"></td> <td class="bg-neutral-5 square sm:square-2"></td> </tr> <tr> <th class="middle normal">.primary </th> <td class="bg-primary-d5 square sm:square-2 "></td> <td class="bg-primary-d4 square sm:square-2 "></td> <td class="bg-primary-d3"></td> <td class="bg-primary-d2"></td> <td class="bg-primary-d1"></td> <td class="bg-primary brx brw-d4 br-white"></td> <td class="bg-primary-1"></td> <td class="bg-primary-2"></td> <td class="bg-primary-3"></td> <td class="bg-primary-4"></td> <td class="bg-primary-5"></td> </tr> <tr> <th class="middle normal">.accent-one </th> <td class="bg-accent-one-d5 square sm:square-2 "></td> <td class="bg-accent-one-d4 square sm:square-2 "></td> <td class="bg-accent-one-d3"></td> <td class="bg-accent-one-d2"></td> <td class="bg-accent-one-d1"></td> <td class="bg-accent-one brx brw-d4 br-white"></td> <td class="bg-accent-one-1"></td> <td class="bg-accent-one-2"></td> <td class="bg-accent-one-3"></td> <td class="bg-accent-one-4"></td> <td class="bg-accent-one-5"></td> </tr> <tr> <th class="middle normal">.accent-two </th> <td class="bg-accent-two-d5 square sm:square-2 "></td> <td class="bg-accent-two-d4 square sm:square-2 "></td> <td class="bg-accent-two-d3"></td> <td class="bg-accent-two-d2"></td> <td class="bg-accent-two-d1"></td> <td class="bg-accent-two brx brw-d4 br-white"></td> <td class="bg-accent-two-1"></td> <td class="bg-accent-two-2"></td> <td class="bg-accent-two-3"></td> <td class="bg-accent-two-4"></td> <td class="bg-accent-two-5"></td> </tr> <tr> <th class="middle normal">.accent-three </th> <td class="bg-accent-three-d5 square sm:square-2 "></td> <td class="bg-accent-three-d4 square sm:square-2 "></td> <td class="bg-accent-three-d3"></td> <td class="bg-accent-three-d2"></td> <td class="bg-accent-three-d1"></td> <td class="bg-accent-three brx brw-d4 br-white"></td> <td class="bg-accent-three-1"></td> <td class="bg-accent-three-2"></td> <td class="bg-accent-three-3"></td> <td class="bg-accent-three-4"></td> <td class="bg-accent-three-5"></td> </tr> </table> </div> <div class="breakout"> <h3 class="max-width-rg">Apply Colors to Text, Background, and Borders</h3> <p class="max-width-rg">Set color, background-color and border-color by applying the naming conventions: </p> <table class="br-separate"> <tr> <th class="left">Color</th> <th class="center">Background</th> <th class="center">Border</th> <th class="below-sm:hide">Refine</th> </tr> <tr> <td class="neutral code middle left">.neutral</td> <td class="bg-neutral white code middle center">.bg-neutral</td> <td class="br brw-d3 neutral br-neutral middle code center">.br-neutral</td> <td class="neutral code middle below-sm:hide">neutral-d5 … neutral-5</td> </tr> <tr> <td class="primary code middle left">.primary</td> <td class="bg-primary white middle code center">.bg-primary</td> <td class="primary br-primary middle br brw-d3 code center">.br-primary</td> <td class="primary code middle below-sm:hide">primary-d5 … primary-5</td> </tr> <tr> <td class="accent-one code middle left">.accent-one</td> <td class="bg-accent-one white middle code center">.bg-accent-one</td> <td class="accent-one br-accent-one middle br brw-d3 code center">.br-accent-one</td> <td class="accent-one code middle below-sm:hide">accent-one-d5 … accent-one-5</td> </tr> <tr> <td class="accent-two code middle left">.accent-two</td> <td class="bg-accent-two white code middle center">.bg-accent-two</td> <td class="accent-two br-accent-two br brw-d3 code middl ecenter">.br-accent-two</td> <td class="accent-two code middle below-sm:hide">accent-two-d5 … accent-two-5</td> </tr> <tr> <td class="accent-three pdb-d2 code middle left">.accent-three</td> <td class="bg-accent-three pdb-d2 white code middle center">.bg-accent-three</td> <td class="accent-three pdb-d2 br-accent-three br brw-d3 code middle center">.br-accent-three </td> <td class="accent-three pdb-d2 code below-sm:hide middle">accent-three-d5 … accent-three-5</td> </tr> </table> </div> <div> <h3>Edge Values</h3> <p>In addition there are the following color classes available:</p> <dl> <dt class="square-1 bg-base-color float-left"></dt> <dd class="mrl-2"><code>.base-color</code> (which is default text-color). <p>The color can be used as text color, background color and border color. It is defined through:</p> <pre>:root { --base-color: var(--neutral-color-d5); }</pre> </dd> </dl> <dl> <dt class="square-1 br br-base-color float-left"></dt> <dd class="mrl-2"><code>.base-background</code> <p>The color can be used as text color, background color and border color. It is defined through: </p> <pre>:root { --base-background: white; }</pre> </dd> </dl> <dl> <dt class="square-1 float-left" style="background: var(--link-hover-color);"></dt> <dd class="mrl-2"> <p>Link colors are not set with dedicated CSS classes. The configuration is only possible by assigning values to the following CSS variables:</p> <pre>:root { --link-color: var(--base-color); --link-active-color: var(--primary); --link-hover-color: var(--primary); }</pre> </dd> </dl> <dl> <dt class="square-1 float-left" style="background: var(--selection-color);"></dt> <dd class="mrl-2"> <p>The color to indicate selected text. The configuration is only possible by assigning values to the following CSS variable:</p> <pre>:root { --selection-color: var(--primary-4); }</pre> </dd> </dl> <dl> <dt class="square-1 bg-black float-left"></dt> <dd class="mrl-2"><code>.black</code> <p>The color can be used as text color, background color and border color. It is defined through: </p> <pre>:root { --black: black; }</pre> </dd> </dl> <dl> <dt class="square-1 br br-base-color float-left"></dt> <dd class="mrl-2"><code>.white</code> <p>The color can be used as text color, background color and border color. It is defined through: </p> <pre>:root { --white: white; }</pre> </dd> </dl> <dl> <dt class="square-1 mark float-left"></dt> <dd class="mrl-2"><code>.mark</code>, <code>mark</code> <p>The color is defined through:</p> <pre>:root { --mark-background: yellow; }</pre> </dd> </dl> <dl> <dt class="square-1 kbd float-left"></dt> <dd class="mrl-2"><code>.kbd</code>, <code>kbd</code> <p>The color is defined through:</p> <pre>:root { --kbd-background: var(--neutral-4); }</pre> </dd> </dl> <dl> <dt class="square-1 bg-meta-color float-left"></dt> <dd class="mrl-2"><code>.meta-color</code> <p>The color can be used as text color and background color. It is defined through: </p> <pre>:root { --meta-color: var(--neutral-d2); }</pre> </dd> </dl> </div> <div> <h3>Define Your Own Color System</h3> <p>The color system is built around the five colors:</p> <dl> <dt class="square-1 bg-neutral float-left"></dt> <dd class="mrl-2">neutral</dd> </dl> <dl> <dt class="square-1 bg-primary float-left"></dt> <dd class="mrl-2">primary</dd> </dl> <dl> <dt class="square-1 bg-accent-one float-left"></dt> <dd class="mrl-2">accent one</dd> </dl> <dl> <dt class="square-1 bg-accent-two float-left"></dt> <dd class="mrl-2">accent two</dd> </dl> <dl> <dt class="square-1 bg-accent-three float-left"></dt> <dd class="mrl-2">accent three</dd> </dl> <p>To define your own color palette, change the colors by providing their hsl color code.</p> <pre class="mid">:root { --neutral-h: 0; --neutral-s: 0%; --neutral-l: 58%; --primary-h: 213; --primary-s: 19%; --primary-l: 60%; --accent-one-h: 3; --accent-one-s: 100%; --accent-one-l: 61%; --accent-two-h: 28; --accent-two-s: 100%; --accent-two-l: 55%; --accent-three-h: 52; --accent-three-s: 100%; --accent-three-l: 50%; }</pre> </div> <h2 id="white-space">White Space</h2> <div> <h3>Notation</h3> <table> <tr> <th>Shorthand</th> <th>Description</th> </tr> <tr> <td>gp</td> <td>grid gap</td> </tr> <tr> <td>mr</td> <td>margin</td> </tr> <tr> <td>pd</td> <td>padding</td> </tr> <tr> <td>t</td> <td>top</td> </tr> <tr> <td>r</td> <td>right</td> </tr> <tr> <td>b</td> <td>bottom</td> </tr> <tr> <td>l</td> <td>left</td> </tr> <tr> <td>n</td> <td>negative</td> </tr> <tr> <td>0 (zero)</td> <td>none</td> </tr> <tr> <td>x</td> <td>X-axis</td> </tr> <tr> <td>y</td> <td>Y-axis</td> </tr> </table> </div> <h3>Margin</h3> <div class="breakout x-12 gp-1 mxw-md"> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-0 inline-block middle"></div> </div> <div><code>.mr-0</code>, <code>.no-mr</code></div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr inline-block middle"></div> </div> <div><code>.mr</code> <small>(1rem)</small></div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mry inline-block middle"></div> </div> <div class="code">.mry</div> </div> <div class="sm:xx-6 rg:xx-6"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mrx inline-block middle"></div> </div> <div class="code">.mrx</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block bottom"> <div class="square-3 bg-neutral-4 mrt inline-block bottom"></div> </div> <div class="code">.mrt</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block bottom"> <div class="square-3 bg-neutral-4 mrr inline-block bottom"></div> </div> <div class="code">.mrr</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block bottom"> <div class="square-3 bg-neutral-4 mrb inline-block bottom"></div> </div> <div class="code">.mrb</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block bottom"> <div class="square-3 bg-neutral-4 mrl inline-block bottom"></div> </div> <div class="code">.mrl</div> </div> <div>Negative margins are supported:</div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mrtn inline-block middle"></div> </div> <div class="code">.mrtn</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mrrn inline-block middle"></div> </div> <div class="code">.mrrn</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mrbn inline-block middle"></div> </div> <div class="code">.mrbn</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mrln inline-block middle"></div> </div> <div class="code">.mrln</div> </div> <div>Use auto margins to position horizontally:</div> <div> <div class="br"> <div class="square-3 bg-neutral-4 mrr-auto"></div> </div> <div class="code">.mrr-auto</div> </div> <div> <div class="br"> <div class="square-3 bg-neutral-4 mrx-auto"></div> </div> <div class="code">.mrx-auto</div> </div> <div> <div class="br"> <div class="square-3 bg-neutral-4 mrl-auto"></div> </div> <div class="code">.mrl-auto</div> </div> <div>In combination with <a href="#flexbox">flexbox</a>, vertical auto margins are possible.</div> <div class="sm:xx-6"> <div class="square-4 flex br"> <div class="square-3 bg-neutral-4 mrt-auto mrx-auto"></div> </div> <div class="code">.mrt-auto.mrx-auto</div> </div> <div class="sm:xx-6"> <div class="square-4 flex br"> <div class="square-3 bg-neutral-4 mrb-auto mrx-auto"></div> </div> <div class="code">.mrb-auto.mrx-auto</div> </div> <div class="sm:xx-6"> <div class="square-4 flex br"> <div class="square-3 bg-neutral-4 mry-auto"></div> </div> <div class="code">.mry-auto</div> </div> <div class="sm:xx-6"> <div class="square-4 flex br"> <div class="square-3 bg-neutral-4 mr-auto"></div> </div> <div class="code">.mr-auto</div> </div> <div>The margin patterns can be applied to decreased and increased margins:</div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-d5 inline-block middle"></div> </div> <div><code>.mr-d5</code> <small>(1px)</small></div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-d4 inline-block middle"></div> </div> <div><code>.mr-d4</code> <small>(2px)</small></div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-d3 inline-block middle"></div> </div> <div><code>.mr-d3</code> <small>(3px)</small></div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-d2 inline-block middle"></div> </div> <div class="code">.mr-d2</div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-d1 inline-block middle"></div> </div> <div class="code">.mr-d1</div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr inline-block middle"></div> </div> <div><code>.mr</code> <small>(1rem)</small></div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-1 inline-block middle"></div> </div> <div class="code">.mr-1</div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-2 inline-block middle"></div> </div> <div class="code">.mr-2</div> </div> <div> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-3 inline-block middle"></div> </div> <div class="code">.mr-3</div> </div> <div class="overflow-hidden"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-4 inline-block middle"></div> </div> <div class="code">.mr-4</div> </div> <div class="overflow-hidden"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-5 inline-block middle"></div> </div> <div class="code">.mr-5</div> </div> <div class="overflow-hidden"> <div class="br inline-block middle"> <div class="square-3 bg-neutral-4 mr-6 inline-block middle"></div> </div> <div class="code">.mr-6</div> </div> </div> <h3>Padding</h3> <div class="breakout x-12 gp-1 mxw-md"> <div> <div class="bg-neutral-4 inline-block pd-0">Padding</div> <div><code>.pd-0</code>, <code>.no-pd</code></div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pd inline-block">Padding</div> <div><code>.pd</code> <small>(1rem)</small></div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pdy inline-block">Padding</div> <div class="code">.pdy</div> </div> <div class="rg:xx-6"> <div class="bg-neutral-4 pdx inline-block">Padding</div> <div class="code">.pdx</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pdt inline-block">Padding</div> <div class="code">.pdt</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pdr inline-block">Padding</div> <div class="code">.pdr</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pdb inline-block">Padding</div> <div class="code">.pdb</div> </div> <div class="sm:xx-6 rg:xx-3"> <div class="bg-neutral-4 pdl inline-block">Padding</div> <div class="code">.pdl</div> </div> <div>The padding patterns can be applied to decreased and increased paddings:</div> <div> <div class="bg-neutral-4 pd-d5 inline-block">Padding</div> <div><code>.pd-d5</code> <small>(1px)</small></div> </div> <div> <div class="bg-neutral-4 pd-d4 inline-block">Padding</div> <div><code>.pd-d4</code> <small>(2px)</small></div> </div> <div> <div class="bg-neutral-4 pd-d3 inline-block">Padding</div> <div><code>.pd-d3</code> <small>(3px)</small></div> </div> <div> <div class="bg-neutral-4 pd-d2 inline-block">Padding</div> <div><code>.pd-d2</code></div> </div> <div> <div class="bg-neutral-4 pd-d1 inline-block">Padding</div> <div><code>.pd-d1</code></div> </div> <div> <div class="bg-neutral-4 pd inline-block">Padding</div> <div><code>.pd</code> <small>(1rem)</small></div> </div> <div> <div class="bg-neutral-4 pd-1 inline-block">Padding</div> <div><code>.pd-1</code></div> </div> <div> <div class="bg-neutral-4 pd-2 inline-block">Padding</div> <div><code>.pd-2</code></div> </div> <div> <div class="bg-neutral-4 pd-3 inline-block">Padding</div> <div><code>.pd-3</code></div> </div> <div class="overflow-hidden"> <div class="bg-neutral-4 pd-4 inline-block">Padding</div> <div><code>.pd-4</code></div> </div> <div class="overflow-hidden"> <div class="bg-neutral-4 pd-5 inline-block">Padding</div> <div><code>.pd-5</code></div> </div> <div class="overflow-hidden"> <div class="bg-neutral-4 pd-6 inline-block">Padding</div> <div><code>.pd-6</code></div> </div> </div> <h3 class="mrb-1">Grid Gap</h3> <div class="x-12 gp-0 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-0</code>, <code>.no-gp</code> <div class="x-12 gp mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp</code> <small>(1rem)</small> <div class="x-12 gpx mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gpx</code> <small>(1rem)</small> <div class="x-12 gpy gpx-0 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gpy.gpx-0</code> <small>(1rem)</small> <div class="mrt-1">All grid gap patterns can be applied to decreased and increased gaps.</div> <div class="x-12 gp-d5 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-d5</code> <small>(1px)</small> <div class="x-12 gp-d4 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-d4</code> <small>(2px)</small> <div class="x-12 gp-d3 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-d3</code> <small>(3px)</small> <div class="x-12 gp-d2 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-d2</code> <div class="x-12 gp-d1 mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp-d1</code> <div class="x-12 gp mrt-1 middle center"> <div class="xx-6 bg-neutral-4 pdy">1</div> <div class="xx-6 bg-neutral-4 pdy">2</div> <div class="xx-6 bg-neutral-4 pdy">3</div> <div class="xx-6 bg-neutral-4 pdy">4</div> </div> <code>.gp</code> <small>(1rem)</small> <h2 id="borders">Borders</h2> <h3>Notation</h3> <table> <tr> <th>Shorthand</th> <th>Description</th> </tr> <tr> <td>br</td> <td>border</td> </tr> <tr> <td>brw</td> <td>border width</td> </tr> <tr> <td>t</td> <td>top</td> </tr> <tr> <td>r</td> <td>right</td> </tr> <tr> <td>b</td> <td>bottom</td> </tr> <tr> <td>l</td> <td>left</td> </tr> <tr> <td>0 (zero)</td> <td>none</td> </tr> <tr> <td>x</td> <td>X-axis</td> </tr> <tr> <td>y</td> <td>Y-axis</td> </tr> </table> <h3>Border</h3> <div class="x-12 gp-1"> <div class="xx-4 br pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br</code></div> <div class="xx-4 bry pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.bry</code></div> <div class="xx-4 brx pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brx</code></div> <div class="xx-4 brt pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brt</code></div> <div class="xx-4 brr pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brr</code></div> <div class="xx-4 brb pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brb</code></div> <div class="xx-4 brl pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brl</code></div> <div class="xx-4 no-br pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.no-br</code></div> </div> <div class="x-12 gp-1"> <h3 class="mrb-0">Border Style</h3> <div class="xx-4 br dashed pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.dashed</code></div> <div class="xx-4 br dotted pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.dotted</code></div> <div class="xx-4 br solid pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.solid</code></div> </div> <div class="x-12 gp-1"> <h3 class="mrb-0">Border Width</h3> <div class="xx-4 br brw-0 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.brw-0</code>, <code>.no-br</code></div> <div class="xx-4 br brw-d5 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw-d5</code>, <code>br.brw-default</code> <small>(1px)</small></div> <div class="xx-4 br brw-d4 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw-d4</code> <small>(2px)</small></div> <div class="xx-4 br brw-d3 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw-d3</code> <small>(3px)</small></div> <div class="xx-4 br brw-d2 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw-d2</code></div> <div class="xx-4 br brw-d1 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw-d1</code></div> <div class="xx-4 br brw pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.brw</code> <small>(1rem)</small></div> </div> <h3>Border Radius</h3> <div class="x-12 gp-1"> <div class="xx-4 br radius-0 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius-0</code></div> <div class="xx-4 br radius-d3 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius-d3</code>, <code>.br.rounded</code></div> <div class="xx-4 br radius-d2 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius-d2</code></div> <div class="xx-4 br radius-d1 pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius-d1</code></div> <div class="xx-4 br radius pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius</code> <small>(1rem)</small></div> <div class="xx-4 br radius-pill pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius-pill</code></div> <div class="xx-4"> <div class="br radius-100 pd-2 inline-block bg-neutral-4"></div> </div> <div class="xx-8"><code>.br.radius-100</code></div> <div class="xx-4 br radius radius-t pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-t</code></div> <div class="xx-4 br radius radius-tl pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-tl</code></div> <div class="xx-4 br radius radius-tr pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-tr</code></div> <div class="xx-4 br radius radius-r pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-r</code></div> <div class="xx-4 br radius radius-b pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-b</code></div> <div class="xx-4 br radius radius-bl pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-bl</code></div> <div class="xx-4 br radius radius-br pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-br</code></div> <div class="xx-4 br radius radius-l pd-1 bg-neutral-4"></div> <div class="xx-8"><code>.br.radius.radius-l</code></div> </div> <h2 id="tables">Tables</h2> <h3>Basic Table</h3> <table> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td> <td>Maria Anders</td> <td>Germany</td> </tr> <tr> <td>Centro comercial Moctezuma</td> <td>Francisco Chang</td> <td>Mexico</td> </tr> <tr> <td>Ernst Handel</td> <td>Roland Mendel</td> <td>Austria</td> </tr> <tr> <td>Island Trading</td> <td>Helen Bennett</td> <td>UK</td> </tr> <tr> <td>Laughing Bacchus Winecellars</td> <td>Yoshi Tannamuri</td> <td>Canada</td> </tr> <tr> <td>Magazzini Alimentari Riuniti</td> <td>Giovanni Rovelli</td> <td>Italy</td> </tr> </table> <pre>table/</pre> <p>Apply padding with <code>.pd</code>, <code>.pdx</code>, or <code>.pdy</code> styling which can be assigned to the table, rows or td and th elements.</p> <p>Borders can be used with <code>.br</code>, <code>.brx</code>, <code>.bry</code>, <code>.brt</code>, <code>.brr</code>, <code>.brb</code>, <code>.brl</code> and <code>.brw</code> styling.</p> <h3>Alternate Table Row Background</h3> <table class="alternate-rows"> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td> <td>Maria Anders</td> <td>Germany</td> </tr> <tr> <td>Centro comercial Moctezuma</td> <td>Francisco Chang</td> <td>Mexico</td> </tr> <tr> <td>Ernst Handel</td> <td>Roland Mendel</td> <td>Austria</td> </tr> <tr> <td>Island Trading</td> <td>Helen Bennett</td> <td>UK</td> </tr> <tr> <td>Laughing Bacchus Winecellars</td> <td>Yoshi Tannamuri</td> <td>Canada</td> </tr> <tr> <td>Magazzini Alimentari Riuniti</td> <td>Giovanni Rovelli</td> <td>Italy</td> </tr> </table> <pre>table/ .alternate-rows</pre> <h3>Alternate Table Column Background</h3> <table class="alternate-cols"> <colgroup> <col> <col> <col> </colgroup> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td> <td>Maria Anders</td> <td>Germany</td> </tr> <tr> <td>Centro comercial Moctezuma</td> <td>Francisco Chang</td> <td>Mexico</td> </tr> <tr> <td>Ernst Handel</td> <td>Roland Mendel</td> <td>Austria</td> </tr> <tr> <td>Island Trading</td> <td>Helen Bennett</td> <td>UK</td> </tr> <tr> <td>Laughing Bacchus Winecellars</td> <td>Yoshi Tannamuri</td> <td>Canada</td> </tr> <tr> <td>Magazzini Alimentari Riuniti</td> <td>Giovanni Rovelli</td> <td>Italy</td> </tr> </table> <pre>table/ .alternate-cols</pre> <h3>Underline Table Rows</h3> <table class="underline-rows"> <tr> <th>Company</th> <th>Contact</th> <th>Country</th> </tr> <tr> <td>Alfreds Futterkiste</td> <td>Maria Anders</td> <td>Germany</td> </tr> <tr> <td>Centro comercial Moctezuma</td> <td>Francisco Chang</td> <td>Mexico</td> </tr> <tr> <td>Ernst Handel</td> <td>Roland Mendel</td> <td>Austria</td> </tr> <tr> <td>Island Trading</td> <td>Helen Bennett</td> <td>UK</td> </tr> <tr> <td>Laughing Bacchus Winecellars</td> <td>Yoshi Tannamuri</td> <td>Canada</td> </tr> <tr> <td>Magazzini Alimentari Riuniti</td> <td>Giovanni Rovelli</td> <td>Italy</td> </tr> </table> <pre class="mrt-1">table/ .underline-rows</pre> <h2 id="figures">Figures</h2> <figure> <img loading="lazy" src="https://ulf.codes/i/compose/pierre-chatel-innocenti-unsplash.jpg" /> <figcaption>Photo by Pierre Chatel on Unsplash</figcaption> </figure> <pre>figure img/ figcaption/ /figure</pre> <figure> <figcaption>Photo by Matthew Henry on Unsplash</figcaption> <img loading="lazy" src="https://ulf.codes/i/compose/matthew-henry-unsplash.jpg" /> </figure> <pre>figure figcaption/ img/ /figure</pre> <figure> <figcaption class="mrl-auto">Photo by Matthew Henry on Unsplash</figcaption> <img loading="lazy" src="https://ulf.codes/i/compose/matthew-henry-unsplash.jpg" /> </figure> <pre>figure figcaption/ .mrl-auto img/ /figure</pre> <h2 id="images">Images</h2> <h3>Responsive Images</h3> <p>Images are by default responsive and take the entire available horizontal space (up to the width of the image) while preserving aspect-ratio.</p> <div class="breakout-wide"> <figure> <img loading="lazy" class="width-100" src="https://ulf.codes/i/compose/swan-leroi-unsplash.jpg" /> <figcaption>Photo by Swan Leroi on Unsplash</figcaption> </figure> </div> <pre class="breakout mr-0">img/ .width-100 //will consume the entire available width, may enlarge the image while preserving aspect ratio</pre> <h3>Contained Images</h3> <p>If the image has a fixed width or fixed height, the usage of <code>.fix-contain</code> will put the entire visible image inside of the given dimensions while preserving aspect-ratio and without stretching the image.</p> <p>Combine <code>.fit-contain</code> with fit positions </p> <ul class="reset mrb-0"> <li><code>.fit-center</code> <small>(default)</small></li> <li><code>.fit-top</code></li> <li><code>.fit-top-left</code></li> <li><code>.fit-top-right</code></li> <li><code>.fit-right</code></li> <li><code>.fit-bottom</code></li> <li><code>.fit-bottom-left</code></li> <li><code>.fit-bottom-right</code></li> <li><code>.fit-left</code></li> </ul> <div class="breakout x-12"> <div class="xx-12 rg:xx-6"> <figure> <img loading="lazy" src="https://ulf.codes/i/compose/jayden-chong-unsplash.jpg" style="height:400px; width:100%" class="fit-contain br" /> <figcaption>Photo by Jayden Chong on Unsplash</figcaption> </figure> <pre>img/ .fit-contain</pre> </div> <div class="xx-12 rg:xx-6"> <figure> <img loading="lazy" src="https://ulf.codes/i/compose/jayden-chong-unsplash.jpg" style="height:400px; width:100%" class="fit-contain fit-top-left br" /> <figcaption>Photo by Jayden Chong on Unsplash</figcaption> </figure> <pre>img/ .fit-contain.fit-top-left</pre> </div> <div class="xx-12"> <h3>Cover Images</h3> <p class="mxw-rg">If the image has a fixed widht or fixed height, the usage of <code>.fit-cover</code> will consume the entire available space of the given dimensions while preserving aspect-ratio.</p> <p>The image might be stretched to cover.</p> <figure> <img loading="lazy" src="https://ulf.codes/i/compose/jayden-chong-unsplash.jpg" style="height:400px; width:100%" class="fit-cover br" /> <figcaption>Photo by Jayden Chong on Unsplash</figcaption> </figure> <pre>img/ .fit-cover</pre> </div> </div> <h3>Background Images</h3> <p>Background images can be positioned with <code>.bg-cover</code>, which is useful for hero banners. In addition, <code>.bg-fixed</code> makes an interesting effect when scrolling over a background image. </p> <div class="breakout-full mry bg-cover bg-fixed bg-center bg-no-repeat height-rg" style='background-image: url("/i/compose/swan-leroi-unsplash.jpg")'> <div class="xl fs-8 lh-2 bold pdy-4 caps lsp overflow-hidden black">Hero</div> </div> <pre class="breakout">div/ .bg-cover.bg-fixed.bg-center.bg-no-repeat.height-rg style="background-image: url('image.jpg')" </pre> <p>Combine <code>.bg-cover</code> with background positions </p> <ul class="reset mrb-0"> <li><code>.bg-center</code></li> <li><code>.bg-top</code></li> <li><code>.bg-top-left</code> <small>(default)</small></li> <li><code>.bg-top-right</code></li> <li><code>.bg-right</code></li> <li><code>.bg-bottom</code></li> <li><code>.bg-bottom-left</code></li> <li><code>.bg-bottom-right</code></li> <li><code>.bg-left</code></li> </ul> <h2 id="x-layout">X Layout</h2> <h3>Centered Layout</h3> <div class="breakout-full bry dotted br-neutral mry code"> div .x <div class="x gpy mry"> <div class="bg-neutral-4 br pd mry"> no class assignment at all </div> <div class="breakout"> <div class="bg-neutral-4 br pd mry">.breakout</div> </div> <div class="breakout-wide"> <div class="bg-neutral-4 br pd mry">.breakout-wide</div> </div> <div class="breakout-full bg-neutral-4 br pd mry"> .breakout-full </div> </div> /div </div> <h3>Left Shifted Layout</h3> <div class="breakout-full bry dotted br-neutral mry code"> div .xl <div class="xl gpy mry"> <div class="bg-neutral-4 br pd mry"> no class assignment at all </div> <div class="breakout bg-neutral-4 br pd mry"> .breakout </div> <div class="breakout-wide"> <div class="bg-neutral-4 br pd mry">.breakout-wide</div> </div> <div class="breakout-full bg-neutral-4 br pd mry"> .breakout-full </div> </div> /div </div> <h2 id="layout">Layout</h2> <h3>Display</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.inline</code></td> <td><code>display: inline;</code></td> </tr> <tr> <td class="no-wrap"><code>.inline-block</code></td> <td><code>display: inline-block;</code></td> </tr> <tr> <td class="no-wrap"><code>.block</code></td> <td><code>display: block;</code></td> </tr> <tr> <td class="no-wrap"><code>.inline-table</code></td> <td><code>display: inline-table;</code></td> </tr> <tr> <td class="no-wrap"><code>.table</code></td> <td><code>display: table;</code></td> </tr> <tr> <td class="no-wrap"><code>.table-cell</code></td> <td><code>display: table-cell;</code></td> </tr> </table> <h3>Align</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.baseline</code></td> <td><code>vertical-align: baseline;</code></td> </tr> <tr> <td class="no-wrap"><code>.top</code></td> <td><code> vertical-align: top;</code></td> </tr> <tr> <td class="no-wrap"><code>.middle</code></td> <td><code> vertical-align: middle;</code></td> </tr> <tr> <td class="no-wrap"><code>.bottom</code></td> <td><code> vertical-align: bottom;</code></td> </tr> <tr> <td class="no-wrap"><code>.left</code></td> <td><code>text-align: left;</code></td> </tr> <tr> <td class="no-wrap"><code>.center</code></td> <td><code>text-align: center;</code></td> </tr> <tr> <td class="no-wrap"><code>.right</code></td> <td><code>text-align: right;</code></td> </tr> <tr> <td class="no-wrap"><code>.justify</code></td> <td><code>text-align: justify;</code></td> </tr> </table> <h3>Overflow</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.overflow-hidden</code></td> <td><code>overflow: hidden;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-x-hidden</code></td> <td><code>overflow-x: hidden;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-y-hidden</code></td> <td><code>overflow-y: hidden;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-auto</code></td> <td><code>overflow: auto;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-x-auto</code></td> <td><code>overflow-x: auto;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-y-auto</code></td> <td><code>overflow-y: auto;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-scroll</code></td> <td><code>overflow: scroll;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-x-scroll</code></td> <td><code>overflow-x: scroll;</code></td> </tr> <tr> <td class="no-wrap"><code>.overflow-y-scroll</code></td> <td><code>overflow-y: scroll;</code></td> </tr> </table> <h3>Box Sizing</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.border-box</code></td> <td><code>box-sizing: border-box;</code> <small>this is default box-sizing for css-compose</small> </td> </tr> <tr> <td class="no-wrap"><code>.content-box</code></td> <td><code>box-sizing: content-box;</code></td> </tr> </table> <h3>Position</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.static</code></td> <td><code>position: static;</code></td> </tr> <tr> <td class="no-wrap"><code>.sticky</code></td> <td><code>position: sticky;</code></td> </tr> <tr> <td class="no-wrap"><code>.relative</code></td> <td><code>position: relative;</code></td> </tr> <tr> <td class="no-wrap"><code>.absolute</code></td> <td><code>position: absolute;</code></td> </tr> <tr> <td class="no-wrap"><code>.fixed</code></td> <td><code>position: fixed;</code></td> </tr> <tr> <td class="no-wrap"><code>.top-0</code></td> <td><code>top: 0;</code></td> </tr> <tr> <td class="no-wrap"><code>.right-0</code></td> <td><code>right: 0;</code></td> </tr> <tr> <td class="no-wrap"><code>.bottom-0</code></td> <td><code>bottom: 0;</code></td> </tr> <tr> <td class="no-wrap"><code>.left-0</code></td> <td><code>left: 0;</code></td> </tr> <tr> <td class="no-wrap"><code>.z-1</code></td> <td><code>z-index: var(--z-1);</code></td> </tr> <tr> <td class="no-wrap"><code>.z-2</code></td> <td><code>z-index: var(--z-2);</code></td> </tr> <tr> <td class="no-wrap"><code>.z-3</code></td> <td><code>z-index: var(--z-3);</code></td> </tr> <tr> <td class="no-wrap"><code>.z-4</code></td> <td><code>z-index: var(--z-4);</code></td> </tr> </table> <h3>Float</h3> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.float-left</code></td> <td><code>float: left;</code></td> </tr> <tr> <td class="no-wrap"><code>.float-right</code></td> <td><code>float: right;</code></td> </tr> <tr> <td class="no-wrap"><code>.float-clear</code></td> <td><code>clear: both;</code></td> </tr> </table> <h3>Clearfix</h3> <p>Using <code>float</code> without <code>.clearfix</code></p> <div> <div class="br brw-d2 br-neutral-3"> <div class="float-left width-4 height-3 bg-base-color"><code class="white">.float-left</code> </div> <div class="float-right width-4 height-3 bg-base-color"><code class="white">.float-right</code> </div> </div> </div> <div class="float-clear"></div> <pre class="mrt">div div/ .float-left div/ .float-right /div</pre> <p class="float-clear mrt-2">Using <code>float</code> with <code>.clearfix</code> assigned to the outer container</p> <div class="br brw-d2 br-neutral-3 clearfix"> <div class="float-left width-4 height-3 bg-base-color"><code class="white">.float-left</code></div> <div class="float-right width-4 height-3 bg-base-color"><code class="white">.float-right</code> </div> </div> <pre class="mid mrt">div .clearfix div/ .float-left div/ .float-right /div</pre> <h2 id="columns">Columns</h2> <p>A flow of a maximum of six columns – each of the same width – can be created for any space.</p> <div class="breakout mxw-lg columns-1 rg:columns-2 md:columns-3 lg:columns-4 indent"> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> <hr> <p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream.</p> <p>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </p> <p>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame.</p> <p>It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather.</p> <p>Drops of rain could be heard hitting the pane, which made him feel quite sad. <span class="quote">How about if I sleep a little bit longer and forget all this nonsense</span>, he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state couldn't get into that position.</p> <p>However hard he threw himself onto his right, he always rolled back to where he was. He must have tried it a hundred times, shut his eyes so that he wouldn't have to look at the floundering legs, and only stopped when he began to feel a mild, dull pain there that he had never felt before.</p> <figcaption> Franz Kafka, <cite>The Metamorphosis</cite></p> </figcaption> </div> <!-- Code Example --> <div class="breakout-full bry mry dotted br-small br-neutral code"> div .xl <div class="xl"> <div class="breakout bg-neutral-4 pd br mry"> .breakout.columns-1.rg:columns-2.md:columns-3.lg:columns-4 </div> </div> /div </div> <p>Alternatively, let the browser decide about the number of columns by assigning <code>.columns-fluid</code>. The CSS property <code>column-width</code> with a default setting of <code>var(--column-fluid-width)</code> is used to create the layout.</p> <p>Use <code>.column-rule</code> to assign a rule between columns. Customize the rule with <code>var(--column-rule)</code>. </p> <div class="breakout mxw-lg columns-fluid column-rule indent"> <p>One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin.</p> <p>He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment.</p> <hr> <p>His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. <span class="quote">What's happened to me?</span> he thought. It wasn't a dream.</p> <p>His room, a proper human room although a little too small, lay peacefully between its four familiar walls. </p> <p>A collection of textile samples lay spread out on the table – Samsa was a travelling salesman – and above it there hung a picture that he had recently cut out of an illustrated magazine and housed in a nice, gilded frame.</p> <p>It showed a lady fitted out with a fur hat and fur boa who sat upright, raising a heavy fur muff that covered the whole of her lower arm towards the viewer. Gregor then turned to look out the window at the dull weather.</p> <p>Drops of rain could be heard hitting the pane, which made him feel quite sad. <span class="quote">How about if I sleep a little bit longer and forget all this nonsense</span>, he thought, but that was something he was unable to do because he was used to sleeping on his right, and in his present state couldn't get into that position.</p> <p>However hard he threw himself onto his right, he always rolled back to where he was. He must have tried it a hundred times, shut his eyes so that he wouldn't have to look at the floundering legs, and only stopped when he began to feel a mild, dull pain there that he had never felt before.</p> <figcaption> Franz Kafka, <cite>The Metamorphosis</cite></p> </figcaption> </div> <!-- Code Example --> <div class="breakout-full mry bry dotted br-small br-neutral code"> div .xl <div class="xl"> <div class="breakout bg-neutral-4 pd br mry"> .breakout.columns-fluid.column-rule </div> </div> /div </div> <h3>Responsive Breakpoints</h3> <p>The column count can vary based on available screen width. Address the different minimum screen sizes with responsive breakpoints, wich are indicated by CSS class prefix values values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The column count is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The column count is applied only if the screen is at least of regular width.</td> </tr> <tr> <td><code>.md:</code></td> <td>The column count is applied only if the screen is at least of mid width.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The column count is applied only if the screen is at least of large width.</td> </tr> </table> <p>A column class without a prefix will be used in case the alternate minimum screen size is not defined.</p> <h2 id="column-grid">12 Column Grid</h2> <p>Any space can be divided horizontally into 12ths by applying the x-12 grid.</p> <p>The sum of the cols per row has to add up to 12. Not specifiying a column size will result in taking the entire grid width into one column.</p> <div class="breakout bry dotted br-small br-neutral mry code"> div .x-12 <div class="x-12 gp center mry"> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-10 br pdy bg-neutral-4">.xx-10</div> <div class="xx-3 br pdy bg-neutral-4">.xx-3</div> <div class="xx-9 br pdy bg-neutral-4">.xx-9</div> <div class="xx-4 br pdy bg-neutral-4">.xx-4</div> <div class="xx-8 br pdy bg-neutral-4">.xx-8</div> <div class="xx-5 br pdy bg-neutral-4">.xx-5</div> <div class="xx-7 br pdy bg-neutral-4">.xx-7</div> <div class="xx-6 br pdy bg-neutral-4">.xx-6</div> <div class="xx-6 br pdy bg-neutral-4">.xx-6</div> <div class="xx-4 br pdy bg-neutral-4">.xx-4</div> <div class="xx-4 br pdy bg-neutral-4">.xx-4</div> <div class="xx-4 br pdy bg-neutral-4">.xx-4</div> <div class="xx-3 br pdy bg-neutral-4">.xx-3</div> <div class="xx-3 br pdy bg-neutral-4">.xx-3</div> <div class="xx-3 br pdy bg-neutral-4">.xx-3</div> <div class="xx-3 br pdy bg-neutral-4">.xx-3</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-2 br pdy bg-neutral-4">.xx-2</div> <div class="xx-12 br pdy bg-neutral-4">.xx-12</div> <div class="br pdy bg-neutral-4">No class assignment</div> </div> /div </div> <h3>Responsive Breakpoints</h3> <p>Columns can have a different width based on minimum screen width. Address the different minimum screen sizes with responsive breakpoints, wich are indicated by CSS class prefix values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The column width is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The column width is applied only if the screen is at least of regular width.</td> </tr> <tr> <td><code>.md:</code></td> <td>The column width is applied only if the screen is at least of mid width.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The column width is applied only if the screen is at least of large width.</td> </tr> </table> <p> A column class without a prefix will be used in case the alternate minimum screen size is not defined. </p> <div class="breakout bry dotted br-small br-neutral mry code"> div .x-12 <div class="x-12 mry gp center"> <div class="xx-12 rg:xx-6 lg:xx-4 br pd middle bg-neutral-4">.xx-12.rg:xx-6.lg:xx-4</div> <div class="xx-12 rg:xx-6 lg:xx-8 br pd middle bg-neutral-4">.xx-12.rg:xx-6.lg:xx-8</div> </div> /div </div> <h2 id="flexbox">Flexbox</h2> <div class="flex justify-start height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-start.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex justify-center height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-center.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex justify-end height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-end.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex justify-space-between height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-space-between.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex justify-space-around height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-space-around.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex justify-space-evenly height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.justify-space-evenly.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex align-start height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.align-start.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex align-center height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.align-center.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex align-end height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.align-end.height-5 div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex align-stretch height-5 bg-neutral-4 white br"> <div class="width-3 mr bg-neutral-d4">1</div> <div class="width-1 mr bg-neutral-d4">2</div> <div class="width-2 mr bg-neutral-d4">3</div> <div class="width-1 mr bg-neutral-d4">4</div> <div class="width-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex.align-stretch.height-5 div 1 /div .width-3 div 2 /div .width-1 div 3 /div .width-2 div 4 /div .width-1 div 5 /div .width-3 /div</pre> <div class="mrt-3 flex align-baseline height-5 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4 fs-3">One Morning</div> <div class="square-3 mr bg-neutral-d4 fs">Gregor Samsa</div> <div class="square-2 mr bg-neutral-d4"></div> <div class="square-1 mr bg-neutral-d4"></div> <div class="square-3 mr bg-neutral-d4"></div> </div> <pre class="mry mid">div .flex.align-baseline.height-5 div 1 /div .square-3 div 2 /div .square-3 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex-wrap bg-neutral-4 white br overflow-x-auto"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-3 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> <div class="square-3 mr bg-neutral-d4">6</div> <div class="square-2 mr bg-neutral-d4">7</div> <div class="square-1 mr bg-neutral-d4">8</div> <div class="square-3 mr bg-neutral-d4">9</div> </div> <pre class="mry mid">div .flex-wrap div 1 /div .square-3 div 2 /div .square-3 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 div 6 /div .square-3 div 7 /div .square-2 div 8 /div .square-1 div 9 /div .square-3 /div</pre> <div class="mrt-3 flex-column align-stretch bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-1 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> </div> <pre class="mry mid">div .flex-column div 1 /div .square-3 div 2 /div .square-1 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 /div</pre> <div class="mrt-3 flex-column flex-wrap overflow-x-auto height-6 bg-neutral-4 white br"> <div class="square-3 mr bg-neutral-d4">1</div> <div class="square-3 mr bg-neutral-d4">2</div> <div class="square-2 mr bg-neutral-d4">3</div> <div class="square-1 mr bg-neutral-d4">4</div> <div class="square-3 mr bg-neutral-d4">5</div> <div class="square-3 mr bg-neutral-d4">6</div> <div class="square-2 mr bg-neutral-d4">7</div> <div class="square-1 mr bg-neutral-d4">8</div> <div class="square-3 mr bg-neutral-d4">9</div> </div> <pre class="mry mid">div .flex-column.flex-wrap.height-6 div 1 /div .square-3 div 2 /div .square-3 div 3 /div .square-2 div 4 /div .square-1 div 5 /div .square-3 div 6 /div .square-3 div 7 /div .square-2 div 8 /div .square-1 div 9 /div .square-3 /div</pre> <h2 id="width">Width, Max-Width, and Min-Width</h2> <p>Set the width by assigning any of the following shorthand CSS classes.</p> <div class="no-wrap overflow-hidden"> <div> <div class="width-unset brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-unset</code> </div> <div> <div class="width-d5 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-d5</code> <small>(1px)</small> </div> <div> <div class="width-d4 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-d4</code> <small>(2px)</small> </div> <div> <div class="width-d3 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-d3</code> <small>(3px)</small> </div> <div> <div class="width-d2 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-d2</code> </div> <div> <div class="width-d1 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-d1</code> </div> <div> <div class="width brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width</code> </div> <div> <div class="width-1 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-1</code> </div> <div> <div class="width-2 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-2</code> </div> <div> <div class="width-3 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-3</code> </div> <div> <div class="width-4 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-4</code> </div> <div> <div class="width-5 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-5</code> </div> <div> <div class="width-6 brb height-1 bg-neutral-4 inline-block mrr"> </div><code>.width-6</code> </div> </div> <div class="breakout-full no-wrap mrt-2 overflow-hidden"> <div class="top brb bg-neutral-4 mxw-sm height-1 mrb-d2 right"> <code class="pdr">.width-sm</code> <small class="sm:hide">there is more →</small> </div> <div class="top brb bg-neutral-4 mxw-rg height-1 mrb-d2 right"> <code class="pdr">.width-rg</code> <small class="rg:hide">there is more →</small> </div> <div class="top brb bg-neutral-4 mxw-md height-1 mrb-d2 right"> <code class="pdr">.width-md</code> <small class="md:hide">there is more →</small> </div> <div class="top brb bg-neutral-4 mxw-lg height-1 mrb-d2 right"> <code class="pdr">.width-lg</code> <small class="lg:hide">there is more →</small> </div> <div class="top brb bg-neutral-4 width-100 height-1 mrb-d2 right"> <code class="pdr">.width-100</code> </div> </div> <p>All <code>.width</code> variations are also available as <code>.max-width</code> and <code>.min-width</code>. Use <code>.mxw</code> as a shorthand for <code>.max-width</code> and use <code>.miw</code> as a shorthand for <code>.min-width</code>. </p> <h3>Responsive Breakpoints</h3> <p>In addition <code>.width</code>, <code>.max-width</code>, and <code>.min-with</code> classes can be altered with responsive breakpoints, wich are indicated by CSS class prefix values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The width is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The width is applied only if the screen is at least of regular width.</td> </tr> <tr> <td><code>.md:</code></td> <td>The width is applied only if the screen is at least of mid width.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The width is applied only if the screen is at least of large width.</td> </tr> </table> <h3>Viewport width</h3> <p>The class <code>.vw-100</code> will assign the exact width of the viewport.</p> <div class="breakout-full"> <div class="brb bg-neutral-4 vw-100 fit height-1 right"> <code class="pdr">.vw-100</code> </div> </div> <h3>Fit</h3> <p>The class <code>.fit</code> will assign a maximum width of 100%.</p> <table> <tr> <th>CSS Class</th> <th>Shorthand for property</th> </tr> <tr> <td class="no-wrap"><code>.fit</code></td> <td><code>max-width: 100%;</code></td> </tr> </table> <h2 id="height">Height, Max-Height, and Min-Height</h2> <div class="no-wrap breakout overflow-hidden"> <div> <div class="inline-block top"> <div class="height-lg width-1 brl bg-neutral-4"> <code class="vertical-rl">.height-lg</code></div> </div> <div class="inline-block top"> <div class="height-md width-1 brl bg-neutral-4"> <code class="vertical-rl">.height-md</code> </div> </div> <div class="inline-block top"> <div class="height-rg width-1 brl bg-neutral-4"> <code class="vertical-rl">.height-rg</code> </div> </div> <div class="inline-block top"> <div class="height-sm width-1 brl bg-neutral-4"> <code class="vertical-rl">.height-sm</code> </div> </div> <div class="inline-block top"> <div class="height-6 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-6</code> </div> <div class="inline-block top"> <div class="height-5 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-5</code> </div> <div class="inline-block top"> <div class="height-4 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-4</code> </div> <div class="inline-block top"> <div class="height-3 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-3</code> </div> <div class="inline-block top"> <div class="height-2 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-2</code> </div> <div class="inline-block top"> <div class="height-1 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-1</code> </div> <div class="inline-block top"> <div class="height width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height</code> </div> <div class="inline-block top"> <div class="height-d1 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-d1</code> </div> <div class="inline-block top"> <div class="height-d2 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-d2</code> </div> <div class="inline-block top"> <div class="height-d3 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-d3</code> </div> <div class="inline-block top"> <div class="height-d4 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-d4</code> </div> <div class="inline-block top"> <div class="height-d5 width-1 brl bg-neutral-4"></div> <code class="vertical-rl block">.height-d5</code> </div> <div class="inline-block"> <div class="height-unset width-1 brl bg-neutral-4 block"> </div> <code class="block width-1 vertical-rl">.height-unset</code> </div> </div> </div> <p>All <code>.height</code> variations are also available as <code>.max-height</code> and <code>.min-height</code>. Use <code>.mxh</code> as a shorthand for <code>.max-height</code> and use <code>.mih</code> as a shorthand for <code>.min-height</code>. </p> <h3>Responsive Breakpoints</h3> <p>In addition the <code>.height</code>, <code>.max-height</code>, and <code>.min-height</code> classes can be altered with responsive breakpoints, wich are indicated by CSS class prefix values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The height is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The height is applied only if the screen is at least of regular width.</td> </tr> <tr> <td><code>.md:</code></td> <td>The height is applied only if the screen is at least of mid width.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The height is applied only if the screen is at least of large width.</td> </tr> </table> <h3>Viewport height</h3> <p>The class <code>.vh-100</code> will assign the exact height of the viewport.</p> <div class="vh-100 brl x-12"> <div class="xx-4 bg-neutral-4"></div> <div class="xx-8"><code>.vh-100</code></div> </div> <h2 id="square">Square</h2> <div class="x-12 gp-1"> <div> <div class="square-d5 bg-accent-one"></div> <code>.square-d5</code> <small>(1px)</small> </div> <div> <div class="square-d4 bg-accent-one"></div> <code>.square-d4</code> <small>(2px)</small> </div> <div> <div class="square-d3 bg-accent-one"></div> <code>.square-d3</code> <small>(3px)</small> </div> <div> <div class="square-d2 bg-neutral-4 br"> </div><code>.square-d2</code> </div> <div> <div class="square-d1 bg-neutral-4 br"></div> <code>.square-d1</code> </div> <div> <div class="square bg-neutral-4 br"></div> <code>.square</code> </div> <div> <div class="square-1 bg-neutral-4 br"></div> <code>.square-1</code> </div> <div> <div class="square-2 bg-neutral-4 br"></div> <code>.square-2</code> </div> <div> <div class="square-3 bg-neutral-4 br"></div> <code>.square-3</code> </div> <div class="overflow-hidden"> <div class="square-4 bg-neutral-4 br"></div> <code>.square-4</code> </div> <div class="overflow-hidden"> <div class="square-5 bg-neutral-4 br"></div> <code>.square-5</code> </div> <div class="overflow-hidden"> <div class="square-6 bg-neutral-4 br"></div> <code>.square-6</code> </div> </div> <div class="breakout-full mrt-2 overflow-hidden"> <div class="square-lg bg-neutral-4 brt brr brb"> <code class="float-right mrr">.square-lg</code> <div class="square-md bg-neutral-4 brr brb"> <code class="float-right mrr">.square-md</code> <div class="square-rg bg-neutral-4 brr brb"> <code class="float-right mrr">.square-rg</code> <div class="square-sm bg-neutral-4 brr brb"> <code class="float-right mrr">.square-sm</code> </div> </div> </div> </div> </div> <h3>Responsive Breakpoints</h3> <p>The <code>.square</code> classes can be altered with responsive breakpoints, wich are indicated by CSS class prefix values of:</p> <table> <tr> <td><code>.sm:</code></td> <td>The square is applied only if the screen is at least of small width.</td> </tr> <tr> <td><code>.rg:</code></td> <td>The square is applied only if the screen is at least of regular width.</td> </tr> <tr> <td><code>.md:</code></td> <td>The square is applied only if the screen is at least of mid width.</td> </tr> <tr> <td><code>.lg:</code></td> <td>The square is applied only if the screen is at least of large width.</td> </tr> </table> <h2 id="hide">Responsive Hide</h2> <div class="breakout-full"> <div class="top brb bg-neutral-4 max-width-sm sm:hide pdx-d1 height-1 mrb-d2 no-wrap"><span class="mrr">Screen has max small width</span><code>.sm:hide</code></div> <div class="top brb bg-neutral-4 max-width-sm below-sm:hide pdx-d1 height-1 mrb-d2 no-wrap"><span class="mrr">Screen has at least small width</span><code>.below-sm:hide</code></div> <div class="top brb bg-neutral-4 max-width-rg below-rg:hide pdx-d1 height-1 mrb-d2"><span class="mrr">Screen has at least regular width</span><code>.below-rg:hide</code> </div> <div class="top brb bg-neutral-4 max-width-md below-md:hide pdx-d1 height-1 mrb-d2"><span class="mrr">Screen has at least mid width</span><code>.below-md:hide</code> </div> <div class="top brb bg-neutral-4 max-width-lg below-lg:hide pdx-d1 height-1 mrb-d2"><span class="mrr">Screen has at least large width</span><code>.below-lg:hide</code> </div> </div> <pre class="breakout mxw-md mry">div/ .sm:hide //When visible: screen has small width or below div/ .below-sm:hide //When visible: screen is above small width div/ .below-rg:hide //When visible: screen is above regular width div/ .below-md:hide //When visible: screen is above mid width div/ .below-lg:hide //When visible: screen is above large width</pre> <table class="mrt-2"> <tr> <th>CSS Class</th> <th>Description</th> </tr> <tr> <td><code>.hide</code></td> <td>Hide in any case</td> </tr> <tr> <td><code class="no-wrap">.sm:hide</code></td> <td>Hide if the screen has at least small screen width. </td> </tr> <tr> <td><code class="no-wrap">.below-sm:hide</code></td> <td>Hide if the screen at max small screen width. </td> </tr> <tr> <td><code class="no-wrap">.rg:hide</code></td> <td>Hide if the screen has at least regular screen width. </td> </tr> <tr> <td><code class="no-wrap">.below-rg:hide</code></td> <td>Hide if the screen has at max regular screen width. </td> </tr> <tr> <td><code class="no-wrap">.md:hide</code></td> <td>Hide if the screen at least mid screen width. </td> </tr> <tr> <td><code class="no-wrap">.below-md:hide</code></td> <td>Hide if the screen at max mid screen width. </td> </tr> <tr> <td><code class="no-wrap">.lg:hide</code></td> <td>Hide if the screen has at least large screen width. </td> </tr> <tr> <td><code class="no-wrap">.below-lg:hide</code></td> <td>Hide if the screen has at max large screen width. </td> </tr> </table> <h2 id="forms">Forms</h2> <form class="mxw-sm"> <dl> <label>Email Address</label> <input type="email" class="width-100 block"> </dl> <dl> <label>Password</label> <input type="password" class="width-100 block"> </dl> <dl> <label>Select</label> <select class="block"> <option>Option 1</option> <option>Option 2</option> <option>Option 3</option> <option>Option 4</option> <option>Option 5</option> </select> </dl> <dl> <label>Datalist</label> <input class="width-100 block" type="list" list="browsers"> <datalist id="browsers"> <option value="Internet Explorer"> <option value="Firefox"> <option value="Chrome"> <option value="Opera"> <option value="Safari"> </datalist> </dl> <dl> <label class="block"> <input type="checkbox" checked> Remember me </label> </dl> <button type="submit">Sign In</button> <button type="reset">Cancel</button> <dl class="inline-block width-100"><label>Textarea</label> <textarea class="block width-100 height-3"></textarea> </dl> </form> </div> </div> </body> <script src="https://ulf.codes/r/dynamic-header.min.js"></script> <script src="https://ulf.codes/r/active-toc.min.js"></script> <script> DynamicHeader.init(); ActiveToc.init(); </script> </html> Sat, 14 Dec 2019 00:00:00 +0000 https://ulf.codes/tools/compose/ https://ulf.codes/tools/compose/tools Dfw <!DOCTYPE HTML> <html> <head> <title>DFW</title> <link href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,600" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Bungee" rel="stylesheet"> </head> <body> <style> * { outline: none; color: #004b87; font-family: 'IBM Plex Sans', sans-serif; line-height: 1.62em; } body { margin: 0; padding: 0; font-size: 19px; background: #004b87; } a { text-decoration: none; } #particles-js { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: #004b87; z-index: -1; } #search { font-size: 19px; padding: 0; margin: 0; max-width: 100%; border: none; border-bottom: 1px solid #004b87; font-weight: 600; } .navigation { background: white; padding: 1.62em; } .wrapper { max-width: 700px; margin: auto; } .navigation h1 { float: left; display: inline; line-height: 1em; margin: 0; padding: 0; font-family: "Bungee"; } .navigation ul { list-style-type: none; margin: 0; padding: 0; margin-left: 10em; } .navigation ul li { padding: 0; margin: 0; margin-bottom: 1em; } .navigation ul li:last-child { margin: 0; } @media only screen and (max-width: 500px) { .navigation h1 { float: unset; display: block; margin-bottom: 1em; } .navigation ul { display:block; margin: 0; } } </style> <div class="navigation"> <div class="wrapper"> <h1>DFW</h1> <ul> <li><a href="#">Quickstart</a></li> <li><a href="#">Documentation</a></li> <li><a href="#">Support</a></li> <li>Search: <input id="search" type="text" autocomplete="off" /></li> </ul> </div> </div> <div id="particles-js"></div> <script src="https://ulf.codes/r/particles.min.js"></script> <script> particlesJS.load('particles-js', '/r/particles.json', function () { console.log('callback - particles.js config loaded'); }); </script> </body> </html> Mon, 18 Mar 2019 00:00:00 +0000 https://ulf.codes/experiments/dfw/ https://ulf.codes/experiments/dfw/experiments stacked-area <p>An <a href="https://www.npmjs.com/package/stacked-area">npm package</a> to draw a SVG stacked area chart with a day-based x-axis.</p> <figure> <img src="https://ulf.codes/i/stacked-area/stacked-area.jpg" /> </figure> Fri, 21 Dec 2018 00:00:00 +0000 https://ulf.codes/tools/stacked-area/ https://ulf.codes/tools/stacked-area/tools cumulative-flow <p>An <a href="https://www.npmjs.com/package/cumulative-flow">npm package</a> to draw a SVG cumulative flow diagram and predict the anticipated completion of work.</p> <figure> <img src="https://ulf.codes/i/cfd/cfd.jpg" /> </figure> Thu, 30 Aug 2018 00:00:00 +0000 https://ulf.codes/tools/cumulative-flow/ https://ulf.codes/tools/cumulative-flow/tools horiz-gauge <p>An <a href="https://www.npmjs.com/package/horiz-gauge">npm package</a> to draw a SVG horizontal gauge. Play with the settings of the horiz-gauge by visiting the <a href="https://htmlpreview.github.io/?https://github.com/ulfschneider/horiz-gauge/blob/master/horiz-gauge-playground.html">horiz-gauge playground</a>.</p> <figure> <img src="https://ulf.codes/i/horiz-gauge/horiz-gauge.jpg" /> </figure> Tue, 12 Jun 2018 00:00:00 +0000 https://ulf.codes/tools/horiz-gauge/ https://ulf.codes/tools/horiz-gauge/tools somap <p>An <a href="https://www.npmjs.com/package/somap">npm package</a> with a sorted map and sorted set, implemented as a binary tree.</p> Sat, 07 Apr 2018 00:00:00 +0000 https://ulf.codes/tools/somap/ https://ulf.codes/tools/somap/tools Breakdown for Atom <p>Breakdown is a <a href="http://atom.io/packages/breakdown">package</a> to be added to your <a href="http://atom.io">Atom</a> editor. It allows you to display and manipulate a breakdown structure of your JIRA Scrum project – even offline and only eventually connected to your JIRA system.</p> <figure> <img src="https://ulf.codes/i/breakdown/breakdown.gif" /> </figure> Sun, 19 Nov 2017 00:00:00 +0000 https://ulf.codes/tools/breakdown/ https://ulf.codes/tools/breakdown/tools dheader <p>An <a href="https://www.npmjs.com/package/dheader">npm package</a> to make the header of your web pages dynamic.</p> <figure> <img src="https://ulf.codes/i/dheader/dynamic-header.gif" /> </figure> Sat, 18 Nov 2017 00:00:00 +0000 https://ulf.codes/tools/dheader/ https://ulf.codes/tools/dheader/tools Splitting User Stories <p>User Stories are short and simple descriptions of a feature told from the perspective of the person who desires the new capability, usually a user or customer of the system. It´s called User Story because you put the user into focus. Therefore a User Story should lead to a product increment that can be seen valuable from the user- or business perspective.</p> <h2 id="the-advantage-of-splitting">The advantage of splitting</h2> <p>A User Story can cover vast amounts of functionality with a single sentence, which requires a team many weeks or even months of work to get it done. Such stories are often called epics. Splitting such stories into pieces which are valuable for users and still deliverable within a Sprint is challenging for many teams. However, there are good reasons why you should do it:</p> <ul> <li>A smaller piece is faster to be delivered than a bigger one, which will bring you in a quicker feedback loop to spot defects in design, code, usability and integration. The sooner a mistake is identified, the less it will cost to fix, and the more time you have to adapt.</li> <li>As you work on small pieces, which can flow smoothly among the professions, like developers, QA engineers, UX/UI engineers, no one has to wait for long while a considerable bunch of work has to get done until the next person can take over.</li> <li>A smaller feature is much easier to understand, and there is less likelihood of a lack of consensus between team members.</li> <li>When slicing a significant function into smaller pieces, you will often realize that not every single bit is required, this will help you to reduce coding, testing, documentation and everything else you need to do to get your software delivered.</li> <li>Small slices allow the team to get small wins on an almost daily basis, leading to much higher engagement.</li> <li>Your daily scrums become far more exciting and useful. Instead of “yeah, I’m 20% done adding all of the new schemas to the DB”, you get “for that story we got the time stamps working in the UI, and today we’re going to make the data persist”.</li> <li>A smaller size tends to make estimates more accurate (though estimates are not too important, as your stories should be small anyway).</li> </ul> <h2 id="jira-is-time-consuming-for-splitting">JIRA is time-consuming for splitting</h2> <p>Trying to break down a User Story within JIRA is very time-consuming and sometimes counter-intuitive. Not to mention that interaction and conversations among people are to be avoided when following this approach, which is the opposite of what you should thrive for. Use a whiteboard or a wall and sticky notes to do the split work, be prepared to change quickly, sketch, refactor and enhance. Only after you have understood what the story is about and how to split in a good way, bring the parts into JIRA.</p> <h2 id="layers">Layers</h2> <p>For engineers who are new to the splitting approach, breaking down stories and still delivering end-to-end functionality within a Sprint is among the most challenging things. That´s because engineers are mostly concerned about finding a way for how to solve the given problem. Their thinking tools have to do with architectural layers, technical components, frameworks and programming languages. Naturally, engineers start splitting by layers, like UI, Business Logic, DB Access, DB, Operating System. Following this approach, they end up with stories for the different architectural layers which will be implemented separately and eventually have to be integrated, which will allow only very late feedback. None of these architecture-layer stories alone will bring value for the user, and in most cases, it´s impossible to come up with a solution during a single Sprint.</p> <p>Also, organizational structures are often formed by their corresponding architecture layers, for example, UI/UX people form an organizational unit, Java developers form a unit, technical writers form a unit, QA engineers form a unit and so on. These units sometimes are called teams. In many cases, none of these “teams” alone can deliver a valuable feature to the user. Which means, costs in terms of understanding, splitting, designing, building, testing and putting into operation are pretty high because the different “teams” need to be coordinated and are interdependent up to the level that they are blocking each other because everyone is waiting for someone else to get work done.</p> <p>Therefore, when talking about splitting User Stories, it´s meant to cut across all layers to come up with end-to-end solutions in each Sprint. The organizational structures have to follow to achieve a delivery-oriented organization. Which leads to small, cross-functional teams, having every skill on-board that is needed to split, design, build, describe, test and deliver an end-to-end feature. This will speed up the feedback loop drastically and thus allows to speed up learning accordingly. The organizational change, of course, is difficult and requires experience and insight. The goal is to have teams being able to operate quick, with minimal interdependencies and end-to-end.</p> <h2 id="patterns">Patterns</h2> <p>Try the following patterns to split your User Stories:</p> <ul> <li><strong>Testing:</strong> When identifying and describing the testable aspects of a User Story, you are already in the kind of thinking that is needed to split the story end-to-end. Thus you have an excellent indication of how to break the story down. Often the essential testable aspects of a Story are described in the so-called acceptance criteria. Just pick that up and use it for your split. This is a perfect way to have QA engineers engaged right from the start.</li> <li><strong>CRUD Operations:</strong> Sometimes you can split a story by its CRUD operations. Watch out for the phrase “manage” in a User Story description – often this indicates a splitting opportunity into Create, Read, Update and Delete parts.</li> <li><strong>Happy and Unhappy:</strong> If you have to take care about things that might go wrong in a User Story, you can use a split for the light flow, where everything goes well and in addition split into the exceptions (unhappy flows), where you handle the problems.</li> <li><strong>Connectors:</strong> User Story descriptions containing connectors like AND, OR, WHEN, IF point you to splitting opportunities.</li> <li><strong>Parameters and Result:</strong> Parameters which determine the function and possible result of a User Story can be used to divide the story. Depending on the number of parameters or the contents of a setting, or the different expected results, you can split along those parameter and result lines.</li> <li><strong>Roles:</strong> In case a User Story describes something that has to be used by different people, groups or roles (e.g. customer, shopper, admin, editor), a split by role might be a good choice. Often you can combine this splitting strategy with the workflow step pattern below, as workflows tend to connect roles via action steps.</li> <li><strong>Workflow Steps:</strong> If a User Story describes a workflow, elaborate if you can make at first two stories, one for the start of the workflow and one for the ending. Followed by subsequent stories which fill the gaps from both endpoints up to the middle.</li> <li><strong>Simple and Complex:</strong> Sometimes you can do a pure core first and subsequently do complex enhancements in additional stories. The workflow steps pattern is some kind of simple and complex pattern, but you can apply simple/complex even without thinking in workflows.</li> <li><strong>Platform:</strong> If you have to support different devices or operating systems (more general: platforms) with a User Story, a natural split is by platform.</li> <li><strong>Vague Terms:</strong> Vague terms offer splitting opportunities by asking what exactly is meant, turning the vagueness into concrete and then applying the above patterns.</li> </ul> <h2 id="concerns">Concerns</h2> <p>Of course, there are teams considering the splitting process to be wasteful and instead finding the implementation of an unsplit functionality to its completeness to be more straightforward and efficient. Recalling one of the advantages from the beginning: Smaller pieces allow faster feedback. Correction at an early point is more direct, much cheaper and will improve your results.</p> <p>Everything in agile software development is about feedback and results. This is because learning is an outcome of feedback and learning on all levels (individual and team) is considered to be the essential ingredient of good software development. Therefore you should give splitting a try!</p> Wed, 15 Nov 2017 00:00:00 +0000 https://ulf.codes/thoughts/splitting-user-stories/ https://ulf.codes/thoughts/splitting-user-stories/thoughts The balanced organization <h2 id="core-cultures">Core cultures</h2> <p>In the agile movement, many consider a collaboration culture as a worthwhile goal for any organization and even further assume the members of those organizations share this goal. This assumption is false. For an organization lacking the heritage of a collaboration culture, turning towards agile will bring only limited results and will not produce insights about what is going on behind the scenes.</p> <p>In general, William Schneider is admitting the possibility of a cultural transformation, but he is also pointing out the difficulty, the risk and the long-term nature (more than ten years) of such an endeavor [Schneider 2000]. Schneider believes that at least 75% of the management has to be convinced about the necessity of a cultural transformation. For this kind of conviction, John Kotter coined the phrase <em>sense of urgency,</em> [Kotter 1996]. Such conditions are seldom to be found.</p> <p>If the current organization is not rooted in a collaborative way of thinking and acting, the organization will only endure agility, but not support or emphasize it. Still, agile projects achieve positive outcomes, but just while getting the low hanging fruits during project runtime. Afterward many of the introduced behavioral changes diminish and daily work is snapping back to how things have always been done around here. As soon as the agile coach is leaving, agile patterns collapse and disappear.</p> <p>In highly competitive and innovative markets there are real advantages in being agile. Agile will help here to get feedback fast, to learn, to decide, to produce results early, to connect with customers and increase employee satisfaction. In an environment where more is unknown than known, where the explorer mindset is vital, the driving forces of agile help to survive and even succeed.</p> <p>When a culture transformation towards collaboration is to time consumptive (of course) and ever pushing with the help of an agile coach without sustainable outcome isn´t satisfying (of course), what is a pragmatic way to get some positive results?</p> <p>William Schneider´s Core Culture Model will allow us to identify the organizations’ current culture and classify it into one of four categories. This can be used as a starting point – understand where the organization is and balance towards a new direction. Any change has to grow from the inside of the organization and has to rely on the strengths of the current culture. Imitating or copying the culture of another organization will not be sustainable. Also keep in mind, that organizational change takes time and will never end; it is a continuous game.</p> <p>Schneider differentiates the following four core cultures:</p> <ul> <li>Control Culture</li> <li>Collaboration Culture</li> <li>Competence Culture</li> <li>Cultivation Culture</li> </ul> <p>Of course, there are more than four organizational cultures, and in reality, probably no organization is identical with another, but with the Core Culture Model reality can be reduced to some important characteristics which play a role in this context. All of the four cultures have specific ways to handle authority, power, leadership, decision making, performance measurement and relations with partners and customers. To understand what that means, let´s go more into detail for each of the core cultures.</p> <h2 id="control-culture">Control Culture</h2> <p>The prototype of this culture is the military. The leadership style is dominant. The more the actions of other people can be influenced and controlled, the better. The more subordinates, the better. Markets are being taken by acquiring, not through innovation. The system is more important than people. Any person is <em>“… like a hand in a bucket of water – when the hand is removed, the water closes in, and there is no trace.”</em> [Schneider 2000:31]</p> <p>The position inside of the hierarchy gives authority. Decisions are being taken impersonally. Information goes top down and bottoms up and less horizontal. Managers will be told what they want to hear from their subordinates. Information hiding is part of this culture. Conflicts are not seen as being healthy and are usually suppressed. Large control cultures tend to be bureaucratic.</p> <p>What is now is valued higher than what might be. Predictability counts.</p> <p>Employees can spend their entire career in one function. People relationships within the same function are close, but relations between functions tend to be distant and formal. People at the top are taking crucial decisions, and if at all, only top management has an integrating effect. Employee performance is measured. Rendered performance is being rewarded; failure to perform will be sanctioned. Individual growth is limited to functional expertise.</p> <p>Innovation rate is low but operational performance can be outstanding. Usually, customers and partners are being ignored, they have to adapt themselves to the system. Ideas for change will quickly be rejected. There is not much room for having fun at work.</p> <p>The control culture is the most widespread organization culture of the last century.</p> <blockquote> <p><em>In one sentence:</em> The system is most important, and big size counts.</p> </blockquote> <h2 id="collaboration-culture">Collaboration Culture</h2> <p>The prototype of the collaboration culture is the family. In competitive situations, it´s about our team against their team. Synergy is vital, and 2 plus 2 sums up to 5 when people are working together and support each other towards a shared goal. Positive and mutual emphasizing relationships propel the team. People feel connected and obliged to their organization – and vice versa. Attitude is <em>“together we win, and alone we lose.”</em> There is not much distance between top management and the workforce. If the organization is having commercial success, all people participate in financial wealth. The collaboration culture is more egalitarian than other cultures. Like an orchestra, all individuals try to behave at their best for the optimal overarching result. Excessive egoism or diva-attitude will not be tolerated.</p> <p>Relationships with customers are partner-oriented. Customers are part of the team, and much energy is invested in understanding the customers and supply to their real demands and needs.</p> <p>Ideas and concepts are essential, but it is people who are nurtured. Loyalty and trust are essential while politics, infighting, and betrayal erode collaboration.</p> <p>Whatever works, is emphasized, particularly what the team decides will work. Pragmatism is part of daily life and initiative of individuals and teams is high. The collaboration culture sees the need for quick change and reacts accordingly. The culture is more tactical than strategic.</p> <p>Leaders put a considerable fraction of their time and energy into team building with a focus on integration. They value different talents and are willing to make personal sacrifices for the good of the larger organization. Communication is with the entire team. Only leaders who contribute and make things happen have authority. The authority is rooted in the relationship power and less in role power. Leaders are firsts among equals.</p> <p>Judgments and decision making are participative and collegial. Information and people find their way quickly to the place where needed. Conflicts are seen to be constructive as they increase the performance of the team.</p> <p>Collaboration cultures can be found in interdisciplinary work environments where speed and complexity come together.</p> <blockquote> <p><em>In one sentence:</em> We are great, and the team comes first.</p> </blockquote> <h2 id="competence-culture">Competence Culture</h2> <p>The prototype of the competence culture is the university. Important are expertise and advancement of knowledge. The motives are excellence, mastery, and achievement of goals. One has to be better than others, has to compete. Authority inside the organization can only be gained through expertise. Competence cultures supply their customers with the best product at a high price.</p> <p>Concepts, ideas and theories are important, and people have to follow. Relationships are on the impersonal side and are defined by the task which has to be achieved. Communication style is informal, unemotional and facts based. The organization ensures a lot of individual freedom as people ask for autonomy and the opportunity for personal achievement. People like to be measured and challenged, to prove they are at the top of their craft.</p> <p>While in the control culture operational systematics are put into focus, the competence culture is giving interest to conceptual systematics. Other than in the control culture, lousy quality will not be tolerated in the competence culture. Members of competence cultures hate it to deliver poor quality. Usually, members of competence cultures feel more connected to their profession than to their organization.</p> <p>The competence culture is a meritocracy. One has to prove and demonstrate competence. One won´t get away with lip service. Behaviour is disciplined and goal oriented. Things will be done right and proper. The search for improvements is never-ending, and challenges are welcomed.</p> <p>The competence culture is future-oriented. Strategic considerations are taken seriously, and derived actions will be performed with consequence. Nevertheless, the new chance will not be overlooked.</p> <p>Leaders are never fully satisfied. They are goal minded and willing to take any decision necessary to achieve those goals. Employees are not bound to a function and move quickly to where their expertise is most suitable for the achievement of a target. Usually, conflicts are handled logical and with reasoning.</p> <p>Competence cultures can be found in innovative markets and niche markets. But the niche can be tall and possibly being dominated by only one organization. In any case, the produced goods or services are exceptional.</p> <blockquote> <p><em>In one sentence:</em> We are exceptional, and we can prove it.</p> </blockquote> <h2 id="cultivation-culture">Cultivation Culture</h2> <p>The prototype of the cultivation culture is the religious community. Personal development, the exploration of own potentials, is the central motif. Values give orientation. There are not many explicit rules, but ethical behavior is essential. The functioning of the organization is ensured through mutual commitments to shared values. A member who is not trustworthy or not dedicated to the values of the organization will have to leave. On the other hand, if someone is recognized as being trustworthy but delivered a bad performance, a second chance will sure be given. Possibly in another, better-suited function with better conditions to grow. In the cultivation culture, people are oriented towards a higher level. It´s being asked for a purpose. Future is an adventure. Relationships are personal, cooperative and interactive. Communication style is open and direct. Ideas of others are enriching own ideas.</p> <p>Among all four core cultures, the cultivation culture can handle change best. Change is being accepted as a part of human life and change will go hand in hand with learning and development. Experimenting is part of daily life to serve recognition.</p> <p>Aesthetics, form, harmony, and fitness are appreciated. The creation of the new, inventing, is a natural affair in the cultivation culture.</p> <p>Members of the culture are empowered towards autonomy with considerable personal freedom. Attitude is optimistic and positive with loyalty for the values of the organization.</p> <p>What could be, is more important than what is. Continuous improvement, as well as ideal solutions, are being searched for and appreciated, while still following values and ethics, which are paramount. Any kind of progress, small or large, will keep things going.</p> <p>Leaders remove obstacles which would impede others to develop their full potential. They trust their employees, are catalysts and exercise control only at a minimum level. They understand themselves as expanders and not controllers of people. They infuse life into the organization. Eccentricity is allowed. Challenging the status-quo, the questioning of dogmas and traditions is desired. Often leaders are enthusiastic, positive and insightful. They are charismatic and inspiring and can put values into operation. They are more defined by followership than by hierarchical power. Decisions will be taken quick but can be changed just as quickly. Conflicts will be managed actively as they are perceived to be valuable and possibly enlightening. Communication style is calm and polite; yelling and screaming are not okay. Instead, the thoughtful exploration of differences is.</p> <p>Organizational structure is decentralized with minimal lines of authority. People are free and encouraged to interact with anyone else in the organization to create. The presence of goodwill is assumed. Information flows freely. Internal competition is minimal because people will help out one another. Individual talent can grow and move in a rather wide range of directions. This is less true of a collaboration culture. Commitment is very high. Employees do the recruiting. Word-of-mouth brings people in.</p> <blockquote> <p><em>In one sentence:</em> Life is fascinating.</p> </blockquote> <h2 id="culture-and-leadership">Culture and leadership</h2> <p>A pure form of the described four cultures does not exist. Any organization has elements of all four cultures. Nevertheless, each organization has a core culture, a dominant culture which all other cultures have to serve. E.g., a military think tank might be driven by competence and collaboration while still serving the general control culture of the military. The connection between leadership and culture is significant. E.g., a cooperative leader can be in a struggle when acting inside of a control culture. Control cultures need bold and clear commands, while the leader would try to intensify collaboration. This can turn to an unresolvable conflict between the leader and the organization.</p> <p>Leadership has to be in line with the problem domain the organization is acting in. Is the domain complex, innovative and competitive, like for example in software development, a control driven leader might not be of much use. Such problem domains demand cooperation and competence.</p> <h2 id="content-and-process">Content and process</h2> <p>William Schneider is classifying his four core cultures by using the dimensions of <em>content</em> and <em>process</em>. <em>Content</em> is what the organization pays attention to; it has the two poles <em>actuality</em> and <em>possibility</em>. <em>Process</em>, on the other hand, describes the communication and decision-making process, which is <em>personal</em> or <em>impersonal</em>.</p> <figure> <img src="https://ulf.codes/i/blog/content_and_process.jpg" /> <figcaption>Figure: Content and process</figcaption> </figure> <p>Control culture and collaboration culture are actuality driven, with collaboration culture being actuality-personal and control culture being actuality-impersonal.</p> <p>Competence and cultivation culture are possibility driven, with competence culture being possibility-impersonal and cultivation culture being possibility-personal.</p> <p>Cultures which differ in content focus <em>and</em> decision taking process are most opposite, as they have nothing in common in the dimensions of <em>content</em> and <em>process</em>. An organizational change from one of these cultures to the opposite other one is the biggest challenge. E.g., a culture change from a control culture to cultivation culture will carry the most significant risk and highest effort, the same is true for a change from collaboration culture to competence culture.</p> <p>It´s more obvious to change to a direct neighbor. It is to decide then what dimension has to be changed. Is it <em>content</em> or <em>process</em>. Should an actuality driven organization move into possibility driven behavior or should an impersonal deciding organization transform into a personal deciding organization? This depends on what is necessary for the organization to survive and to be successful.</p> <h2 id="in-what-culture-am-i-living">In what culture am I living?</h2> <p>The motive to ask about the core culture can be personal or organizational. On an individual basis, you might ask yourself: What is my preferred culture? Does my preferred culture suit with the culture of my current workplace? Am I able to change something with the current culture? Should I leave?</p> <p>On the organizational level, the question about the core culture will produce some insights about the functioning principles and driving forces of the organization. This insight is a prerequisite to handle issues like: Is the current organization efficient enough? What are the current problems? In what environment or market is the organization positioned? Is the culture sufficient for that environment? Organizational changes should be managed with care on top of these insights.</p> <h2 id="agile-methods-and-core-culture">Agile methods and core culture</h2> <p>A control culture characterizes most corporate structures. It is the culture of the last century, for large organizations with a tayloristic production approach with a skilled minority at the top and many followers below which are being told what to do and how to do it. The individual is not so important. Instead, the system is.</p> <p>On the other hand, in the agile movement a collaboration and cultivation culture is propagated. The organization is expected to be smaller and network-oriented; people are much more egalitarian and understand their shared goals. Individuals are essential, and skill levels are high.</p> <p>Agile [<a href="http://agilemanifesto.org">Beck et al 2001</a>] is often used as a paramount phrase for methods like <a href="http://scrumguides.org">Scrum</a>, <a href="https://en.wikipedia.org/wiki/Kanban_(development)">Kanban</a>, <a href="http://extremeprogramming.org">XP</a> and even a value system like the Software Craftsmanship movement [<a href="http://manifesto.softwarecraftsmanship.org">Bradbury et al 2009</a>] is sometimes entitled to be agile. If we take a closer look at these different approaches and map them to William Schneiders core cultures on the dimensions of <em>content</em> and <em>process</em>, some interesting insights reveal.</p> <figure> <img src="https://ulf.codes/i/blog/agile_and_culture.jpg" /> <figcaption>Figure: Agile and culture</figcaption> </figure> <p>Kanban, for example, gives a low-level entry into its working model, because Kanban will let you start where you are now. Kanban will visualize your current workflow without changing it at first. There are no new roles and organizational structures like Sprints or iterations. The cycle time and lead time of the work orders will be measured. At this point waiting queues become visible, are being analyzed and actions will be taken to streamline the workflow. Eventually, WIP limits (work in progress limits) will be introduced at working steps. This exact measuring and not touching current processes at first is well-suited for a control culture and does not require much of any other culture. Still, Kanban could serve as a “gateway drug” for balancing the organization into a collaboration or competence culture, if necessary.</p> <p>The Software Craftsmanship movement and even XP are well suited in a competence culture. Professional expertise on an individual level, holding high of the profession and demanding for quality are essential features of this culture, and the same can be said about XP and Software Craftsmanship.</p> <p>Agile at the core is located in a collaboration and cultivation culture. Michael Sahota deduced this in his “Agile Adoption and Transformation Survival Guide” [Sahota 2012]. The Agile Manifesto reminds us the of the agile values:</p> <ul> <li>Individuals and interactions are valued over processes and tools</li> <li>Working software over comprehensive documentation</li> <li>Customer collaboration over contract negotiation</li> <li>Responding to change over following a plan</li> </ul> <p>Scrum is an excellent representative of a collaboration- and cultivation-minded agile method. A Scrum Team is delivering work with less than ten members by following an iterative delivery approach which is organized into subsequent so-called Sprints, which take between 1 to 4 weeks of duration. The Scrum Team will deliver a working product increment in each Sprint, and they do it together as a team with a shared Sprint Goal. Progress is being measured in working software and is visualized in burndown diagrams. Of course, being able to achieve such kind of a continuous value delivery requires a lot: a value-oriented mindset, a good understanding of customer needs and the ability to break down these needs into functioning pieces which can be delivered in a Sprint. Further, a functioning team structure, exceptional expertise on technical site only to be able to come to a product increment every 1 to 4 weeks – there is a strong connection to the competence culture. Transparency is crucial, and progress is being measured and shared with everyone having an interest in the project – here is some connection to the control culture.</p> <h2 id="how-to-balance-the-current-culture">How to balance the current culture</h2> <p>Assuming the organization has a control culture, the least change and challenge for the organization is to start with Kanban. The current process will be visualized, and performance will be measured.</p> <p>The next step is to correct the dysfunctions of the process. Is the cycle time to slow? Are there waiting queues at some work steps? To analyze those dysfunctions will provide insights to come up with possible improvements. Would it be of help to intensify collaboration? Is the technical expertise and competence on the desired level? This exercise is developing paths to balance the control culture towards a collaboration or competence culture.</p> <figure> <img src="https://ulf.codes/i/blog/balance_the_culture.jpg" /> <figcaption>Figure: Balance the culture</figcaption> </figure> <p>To get this working, at least the will to understand and share insights about the current situation, the will for transparency, is necessary. But this should be inside of the natural range of a control culture, as this culture is actuality-impersonal driven.</p> <p>The success of the balancing actions is, like always, depending on the dedication of the organization leaders. There might be control cultures which resist any change.</p> <p>But with some good will, balancing for the better should be possible inside of any culture and not against the culture. I see this approach to be a realistic answer to the problems of an imperfect world.</p> <h2 id="references">References</h2> <dl> <dt>[Beck et al. 2001]</dt> <dd>K. Beck et al., “Agile Manifesto”, 2001, <a href="http://agilemanifesto.org">http://agilemanifesto.org</a></dd> <dt>[Bradbury et al. 2009]</dt> <dd>D. Bradbury et al., “Manifesto for Software Craftsmanship”, 2009, <a href="http://manifesto.softwarecraftsmanship.org">http://manifesto.softwarecraftsmanship.org</a></dd> <dt>[Cottmeyer 2011]</dt> <dd>M. Cottmeyer, “Untangling Adoption and Transformation”, 2011, <a href="http://www.leadingagile.com/2011/01/untangling-adoption-and-transformation">http://www.leadingagile.com/2011/01/untangling-adoption-and-transformation</a></dd> <dt>[Kanban]</dt> <dd>“Kanban Development”, <a href="https://en.wikipedia.org/wiki/Kanban_(development)">https://en.wikipedia.org/wiki/Kanban_(development)</a></dd> <dt>[Kotter 1996]</dt> <dd>John P. Kotter, “Leading Change”, Harvard Business School Press, 1996</dd> <dt>[Sahota 2012]</dt> <dd>Michael Sahota, “An Agile Adoption and Transformation Survival Guide”, 2012</dd> <dt>[Schneider 2000]</dt> <dd>William E. Schneider, “The Reengineering Alternative”, McGraw-Hill, 2000</dd> <dt>[Scrum]</dt> <dd>“Scrum Guides”, <a href="http://www.scrumguides.org">http://www.scrumguides.org</a></dd> <dt>[XP]</dt> <dd>“Extreme Programming, A gentle introduction”, <a href="http://extremeprogramming.org">http://extremeprogramming.org</a></dd> </dl> Sun, 26 Feb 2017 00:00:00 +0000 https://ulf.codes/thoughts/balanced-organization/ https://ulf.codes/thoughts/balanced-organization/thoughts Tracker <p>File your workout routines and get a nice graphical overview of your achievements and improvements. Go to <a href="http://tracker.peewee.space">tracker.peewee.space</a>, Sign in and start tracking. Tracker is free.</p> <figure> <a href="http://tracker.peewee.space"><img src="https://ulf.codes/i/tracker/tracker.jpg" /></a> </figure> <h2 id="file-a-track">File a track</h2> <p>An example of a filed track is:</p> <blockquote> <p>Today 13:30 #bike 3h46m 94.6km 25.06km/h 995mtr-up //cold ride, started at minus 5°C and came back at plus 5°C</p> </blockquote> <p>Step by step:</p> <ul> <li>Just bring the caret into the text entry field which is labeled <strong>File your track</strong>.</li> <li>Give your track a name. The name must start with <strong>#</strong> or <strong>@</strong>. E.g., use <strong>#bike</strong> to file your epic bike rides.</li> <li>In the example above the ride took 3 hours and 46 minutes (<strong>3h46m</strong>). To make the time units of your duration clear, use <strong>d</strong> for days, <strong>h</strong> for hours, <strong>m</strong> for minutes, <strong>s</strong> for seconds or even <strong>i</strong> for milliseconds.</li> <li>Bring in any other unit which is of interest for you by writing down the number first and adding the unit without a space between the number and the unit. In the above example, we keep track of the distance (<strong>94.6km</strong>), the average speed (<strong>25.06km/h</strong>) and the meters up (<strong>995mtr-up</strong>). You decide how your units are being named.</li> <li>Add a comment, if you like. Everything that comes behind the double slash <strong>//</strong> is treated as a comment. A comment may contain links to web pages.</li> <li>If you don´t specify a date or a time, your track will be filed with the current date and time. You can specify a different date or time in the format <strong>D-MMM-YY HH:mm</strong> (omit the time or the date if either one is not needed). The time format <strong>HH:mm</strong> is 24 hours. If you file a track for the last seven days, you can use the following shortcuts for the date: <strong>today</strong>, <strong>yest</strong>, <strong>yesterday</strong>, <strong>mon</strong>, <strong>tue</strong>, <strong>wed</strong>, <strong>thu</strong>, <strong>fri</strong>, <strong>sat</strong>, <strong>sun</strong>.</li> </ul> <p>Submit your track by pressing ENTER or clicking/touching the Submit button.</p> <h2 id="display-tracks">Display tracks</h2> <p>Tracks are being displayed in two ways: as an ordered table, where the most recent activities are listed at the top, and as a chart, which will visualize all tracks that are contained in the ordered table.</p> <p>In the chart, you can filter down further and hide away those tracks you are currently not interested in. The filter controls visualize the total duration of your tracks, as well as the sum for any other unit that you collected. There is one particular case for your units – if the unit contains a slash (/), like in km/h, which means kilometers per hour, the units are not merely summed up, but the average is being calculated. All figures are only for the currently filtered tracks.</p> <h2 id="query-tracks">Query tracks</h2> <p>Analyze your data by querying specific tracks and time ranges. Place your queries in the text entry field labeled <strong>Query tracks</strong>. An example of a query is:</p> <blockquote> <p>oct..dec #bike</p> </blockquote> <p>This will list all #bike tracks for October, November, and December of the current year. You can select multiple tracks in one query, like <strong>#bike #run</strong>, which would select all #bike and #run tracks. The time range selector allows you to do the following:</p> <ul> <li>Query an entire year, like 2016: <strong>16</strong> or <strong>2016</strong></li> <li>Query a month, like August: <strong>aug</strong></li> <li>Query a range of months for the current year, like in the above example October to December: <strong>oct..dec</strong></li> <li>Query everything from a given date, like from 1st of March 2015: <strong>1-mar-15..</strong></li> <li>Query everything up to a given date, like up to 9th of October 2016: <strong>..9-oct-16</strong></li> <li>Query a date range, like from 1st of March 2015 to 9th of October 2016: <strong>1-mar-15..9-oct-16</strong></li> </ul> <p>Submit your query by pressing ENTER or clicking/touching the Query button.</p> <figure>Enjoy your sports routine!</figure> Wed, 02 Nov 2016 00:00:00 +0000 https://ulf.codes/tools/tracker/ https://ulf.codes/tools/tracker/tools Pocket Git Guide <p>A short entry-level approach to Git</p><h2>Contents</h2> <ul> <li><a href="#reasons-to-use-git">Reasons to use Git</a></li> <li><a href="#get-git-on-your-mac">Get Git on your Mac</a></li> <li><a href="#get-git-on-windows">Get Git on Windows</a></li> <li><a href="#the-git-shell">The Git shell</a></li> <li><a href="#tell-git-who-you-are">Tell Git who you are</a></li> <li><a href="#get-help-from-git">Get help from Git</a></li> <li><a href="#create-a-new-local-repository">Create a new local repository</a></li> <li><a href="#status-of-your-repository">Status of your repository</a></li> <li><a href="#stage-to-tell-git-what-to-refer-to">Stage to tell Git what to refer to</a></li> <li><a href="#commit-to-make-a-snapshot-of-your-work">Commit to make a snapshot of your work</a></li> <li><a href="#the-commit-message">The commit message</a></li> <li><a href="#removing-files">Removing files</a></li> <li><a href="#renaming-files">Renaming files</a></li> <li><a href="#ignoring-files">Ignoring files</a></li> <li><a href="#branch-to-isolate">Branch to isolate</a></li> <li><a href="#compare-your-working-directory">Compare your working directory</a></li> <li><a href="#merge-to-include">Merge to include</a></li> <li><a href="#remove-or-rename-a-branch">Remove or rename a branch</a></li> <li><a href="#rewind-your-work">Rewind your work</a></li> <li><a href="#working-with-remotes-to-share-with-a-team">Working with remotes to share with a team</a></li> <li><a href="#clone-a-remote-repository-to-local">Clone a remote repository to local</a></li> <li><a href="#push-data-to-remote">Push data to remote</a></li> <li><a href="#pull-data-from-remote">Pull data from remote</a></li> <li><a href="#the-big-picture">The big picture</a></li> <li><a href="#command-reference">Commmand reference</a></li> <li><a href="#references">References</a></li> </ul> <h2 id="reasons-to-use-git">Reasons to use Git</h2> <p>Git will help you doing the following things with a computer:</p> <div class="x-12 mrt"> <div class="xx-12 rg:xx-6"> <h2 class="inline">Personal</h2> <ul class="indent mrt-0"> <li>Keep track of file revisions when working iteratively (this is often referred to as version control).</li> <li>Safely experiment because you can always step back to the previous version.</li> <li>No need to give your files version indicating names, like essay_v1.txt, essay_v2.txt and so on.</li> <li>It doesn´t play a role if you want to work on a single file or a multi-file project organized in multiple folders.</li> <li>Convert any file or folder structure into a project that is under version control.</li> <li>Have the advantage of powerful version control without the need to setup a server or creating an account somewhere.</li> <li>Work consistently on multiple different operating systems, like MacOS, Linux and Windows.</li> </ul> </div> <div class="xx-12 rg:xx-6"> <h2 class="inline">Team</h2> <ul class="indent mrt-0"> <li>Share your work with others and keep track of their changes by enforcing the same set of rules for managing versions. This will work even with thousands of persons on a big project, but also scales down nicely for a small team.</li> <li>When sharing your work with others, you can work on your local computer without being always connected to a shared repository, only synchronizing eventually.</li> <li>No central locking of files. All team members have their own working copy on their own computers which allows each of them to work independently.</li> </ul> </div> </div> <p>Git is free. You can get Git for any platform at <a href="https://git-scm.com/downloads">git-scm.com/downloads</a>.</p> <h2 id="get-git-on-your-mac">Get Git on your Mac</h2> <p>I find it a little bit faster and more comfortable to use the <a href="https://desktop.github.com">GitHub Desktop Installer</a> for setting up Git on either Mac or Windows.</p> <p>On a Mac, after installation, fire up GitHub Desktop, open the Preferences screen, go to the advanced tab and activate <em>Install Command Line Tools</em> to have the Git shell on your Mac. If you are using GitHub Desktop the first time, you can either install the command line tools from the welcome screen of GitHub Desktop.</p> <p>Though not mandatory, for an improved Git experience in the shell, I like to have the following configured:</p> <ul> <li>The credential helper to cache my username and password, so I don´t have to provide it over and over again when using the https port while connecting to Git servers. See <a href="https://help.github.com/articles/caching-your-github-password-in-git/">Caching Your Git Password</a> for installation advice.</li> <li>Bash Git Completion for an improved command prompt and command completion with the tab key. Follow <a href="https://github.com/bobthecow/git-flow-completion/wiki/Install-Bash-git-completion">Install Bash Git Completion</a> to get it set up (it includes a Git installation via homebrew, but you won´t need that one if you already installed GitHub Desktop like mentioned before). In addition to the explanations given, put the following lines to your <code>.bash_profile</code> to improve your command prompt:</li> </ul> <pre>export GIT_PS1_SHOWDIRTYSTATE=true export GIT_PS1_SHOWUNTRACKEDFILES=true PS1='\u@\h \W$(__git_ps1 " (%s)")\$ '</pre> <h2 id="get-git-on-windows">Get Git on Windows</h2> <p>On Windows, the installation of <a href="https://desktop.github.com">GitHub Desktop</a> will bring Git and the GitHub Desktop Client on your machine. This all with minimal configuration effort for yourself. I think it´s a good starting point for your Git experience on Windows.</p> <blockquote> <p>No matter what platform you are using, all of the examples in this document are to be run from inside a command shell with access to Git.</p> </blockquote> <h2 id="the-git-shell">The Git shell</h2> <p>You can use a slick GUI client on top of Git, like for example <a href="https://www.git-tower.com">Tower</a> on a Mac or the reduced <a href="https://desktop.github.com">GitHub Desktop</a>. Sometimes things go faster and easier with a GUI client. Anyway, an advantage of the command shell is, it works the same on all platforms. What you learned here can be used anywhere. I assume it´s not so bad to start at the bottom to understand the tool right.</p> <h2 id="tell-git-who-you-are">Tell Git who you are</h2> <pre>git config [--global] user.name ["your name or user name"] git config [--global] user.email ["your email address"]</pre> <p>Use the <code>--global</code> option to tell Git that the given configuration will be the default for all of your projects on your computer. After these settings have been made, your user data will be added to your commits. When you then push commits to a shared server, your name and email address will also appear on that server.</p> <p>Detect your configuration settings with <code>git config --list</code>.</p> <h2 id="get-help-from-git">Get help from Git</h2> <p>You can type <code>git help &lt;command&gt;</code> to get access to user documentation about the specified <code>&lt;command&gt;</code>. To only get short info about the command syntax, use <code>git &lt;command&gt; -h</code>.</p> <h2 id="create-a-new-local-repository">Create a new local repository</h2> <p>Move to the folder which should contain your project <code>cd /path/to/your/prj/</code>, then initialize the Git repository for the project with <code>git init</code>.</p> <h2 id="status-of-your-repository">Status of your repository</h2> <p>When inside of a local Git repository <code>git status</code> will tell you what branch you are currently working on and give you an overview of untracked changes and outstanding commits.</p> <h2 id="working-staging-and-committing">Working, staging and committing</h2> <p>Versioning in Git is achieved by creating snapshots of your entire working directory. A snapshot is created with a <em>commit</em>. For files without changes, Git will maintain a reference to the previous snapshot. This means, each commit represents your entire working directory at that time, but stores only the files which have been changed. Technically speaking, Git maintains a <em>directed acyclic graph</em> of snapshots of your work.</p> <figure> <img src="https://ulf.codes/i/blog/git_commits_over_time.jpg" /> <figcaption> Figure: Git produces snapshots of your entire project </figcaption> </figure> <p>While you are working, Git divides your content into three main sections. Your working directory, your staging area (often referred to as <em>index</em>) and your committed work.</p> <ul> <li>Your working directory is merely the set of files and folders you operate on – your project.</li> <li>The staging area is the set of changes which should go into the next commit.</li> <li>Once you commit, Git will take the contents from the staging area and create a snapshot in the Git repository, which is then the committed revision of your project at the time of the commit.</li> </ul> <figure> <img src="https://ulf.codes/i/blog/git_areas.jpg" /> <figcaption>Figure: Working – Staging – Committing</figcaption> </figure> <h2 id="stage-to-tell-git-what-to-refer-to">Stage to tell Git what to refer to</h2> <p>To prepare a snapshot of your current work, which will be stored in the Git repository, call <code>git add &lt;pathspec&gt;</code>.</p> <p><code>&lt;pathspec&gt;</code> specifies the files to be put into the staging area (the index). Wildcards are allowed.</p> <p>If a version of a file is not staged, Git doesn´t know how to refer to that version of the file and therefore you can´t commit it later on. Staged but uncommitted content remains only on your local computer and will not be sent to a remote repository somewhere else.</p> <p>If you omit the <code>&lt;pathspec&gt;</code>, use <code>git add --all</code> which will ensure all untracked files in your current project are being added to your staging area.</p> <p>The opposite of <code>git add</code> is <code>git reset &lt;pathspec&gt;</code>. With <code>git reset</code> you can un-stage contents.</p> <p>If you created files or directories without staging them, and you want to get rid of them, use <code>git clean [-ifd]</code>.</p> <p><code>-i</code> show what would be done and clean files interactively.</p> <p><code>-f</code> if the git config <code>clean.requireForce false</code> is not set, this option is needed to proceed with the command.</p> <p><code>-d</code> will also remove directories in addition to files.</p> <h2 id="commit-to-make-a-snapshot-of-your-work">Commit to make a snapshot of your work</h2> <p>You will commit very often, multiple times a day, sometimes within in minutes. It is the action you do most of the time when using Git.</p> <p>Do not commit half-done, not-functioning work. Any commit should be a small solution for its own. As an example, a commit can contain the refactoring of a single method in your code or the rephrasing of a paragraph in a text document.</p> <p>Contents which have been staged must be committed to produce a snapshot of your current work in the Git repository. Any commit is self-contained, it does not only reference your current changes but everything which makes up the state of your current project at the time you are committing. This is because each commit contains a pointer to its direct predecessor, the parent commit. Beginning at the most recent commit, the <em>tip</em>, the list of commits is a sequence pointing to the past, defining your entire project at the current time.</p> <p>Commit with <code>git commit [-a] [-m "your commit message"]</code>.</p> <p><code>-a</code> is a nice shorthand option even to stage content which has been modified or deleted without a previous <code>git add</code> command. New contents still need to be staged with the <code>git add</code> command. With <code>-m "your commit message"</code> you tell your co-workers and probably yourself why you made the commit.</p> <p>An even shorter form of committing, in that case, is <code>git commit -am "your commit message"</code>.</p> <p>Here the option to stage modified and deleted contents and the option to provide a commit message are combined in one option <code>-am</code>. You can combine multiple options in a single one like here, the only restriction is that only the last option can take an argument, like the commit message.</p> <p>If you don´t specify a commit message when firing the commit command, an editor will be opened where you have to provide the commit message. You can configure the editor of your preference with <code>git config --global core.editor &lt;editor-name&gt;</code>.</p> <p><a href="https://help.github.com/articles/associating-text-editors-with-git/">help.github.com/articles/associating-text-editors-with-git</a> provides a brief guide to setting up several editors. To see the currently configured editor, type <code>git config [--global] core.editor</code>.</p> <p>Once you configured your preferred editor, you can not only write your commit messages by using it, you can also edit all of your configurations easily with the command <code>git config [--global] --edit</code>.</p> <p>To see the history of commits use <code>git log</code>. The output of a <code>git log</code> can be filtered and formatted with <code>git log [--oneline] [--pretty] [&lt;branch-name&gt;]</code>.</p> <p>For example <code>git log --oneline</code> will display most recent commits organized into one single line per commit.</p> <p><code>git log --oneline &lt;branch-name&gt;</code> will display most recent commits in the specified branch, organized into one single line per commit.</p> <p>A free formatting of the <code>git log</code> output can be achieved with <code>git log --pretty="&lt;your format string&gt;"</code></p> <p>A list of available formatting options is on <a href="https://git-scm.com/docs/pretty-formats">git-scm.com/docs/pretty-formats</a>.</p> <h2 id="the-commit-message">The commit message</h2> <p>A <code>git log</code> of commit messages should give an idea of how the project has evolved. Each message explains <em>what</em> has been accomplished or changed with the commit. The message should describe a whole idea of completed work <a href="https://24ways.org/2014/dealing-with-emergencies-in-git/">[Westby 2014]</a>. Don´t describe <em>how</em> the change was accomplished – that´s in the code.</p> <p>A properly formed commit subject line should complete the following sentence:</p> <figure> If applied, this commit will <code>&lt;your commit subject line&gt;</code> </figure> <p>The commit messages reveal whether a committer is a good collaborator or not.</p> <p>Because in the output of a <code>git log</code> is not much space to display text and we do not have time to read through many sentences to understand what a commit was about, as a rule of thumb, the subject of the commit message should contain one line and 50 or fewer characters. Start the subject with a capital letter and do not end with a period.</p> <p>Use the imperative mood, which means “spoken or written as if giving a command or instruction”. Examples:</p> <ul> <li>Repair css class assignment for git_hub image</li> <li>No underline for slide navigation</li> <li>Increase line height by a factor of 0.1</li> </ul> <p>If more explanation is needed, let a blank line follow the subject and then write the body of the commit message, wrapped at 72 characters per line, as Git will not wrap text automatically. Explain <em>why</em> the commit was made, again, not <em>how</em>.</p> <p>In other words, follow the seven rules of a great Git commit message <a href="http://chris.beams.io/posts/git-commit/#separate">[Beams 2014]</a>:</p> <ol> <li>Use the imperative mood in the subject line</li> <li>Limit the subject to 50 characters</li> <li>Capitalize the subject line</li> <li>Do not end the subject line with a period</li> <li>Separate the subject from the body with a blank line</li> <li>Wrap the body at 72 characters</li> <li>Use the body to explain <em>what and why</em> vs. <em>how</em></li> </ol> <h2 id="removing-files">Removing files</h2> <p>To delete a file from the working copy and the staging index, use <code>git rm &lt;pathspec&gt;</code>.</p> <p><code>&lt;pathspec&gt;</code> describes the file or even files (wildcards allowed), which should be deleted. <code>git rm</code> will remove the file in your working copy and will stage the remove so that the removal can be committed in a subsequent commit. If you forgot to use <code>git rm</code> at first hand and instead removed the file with your usual remove command in the shell, the file will be removed from the working copy, but not from the staging index. In that case, you can even call <code>git rm &lt;pathspec&gt;</code> afterward, to have the file be removed from the index, as it is already removed from the file system.</p> <h2 id="renaming-files">Renaming files</h2> <p>If you rename a file in your command shell with <code>mv a.txt b.txt</code>, it will produce a similar situation as if you would remove a file with just the shell command <code>rm a.txt</code> and creating a new file <code>b.txt</code>. Git would still try to keep track of <code>a.txt</code>. To fix this, you would have to</p> <pre>git rm a.txt git add b.txt</pre> <p>Or, use the suitable Git command right from the start: <code>git mv a.txt b.txt</code> which can be generalized to <code>git mv &lt;current-path&gt; &lt;new-path&gt;</code></p> <h2 id="ignoring-files">Ignoring files</h2> <p>If Git should ignore some files in your project, for example, because</p> <ul> <li>a process belonging to your project automatically creates the files,</li> <li>the files contain credentials or</li> <li>package managers anyway download the files,</li> </ul> <p>you can specify patterns inside of the <code>.gitignore</code> file to exclude these from Git version control. Each pattern is one line in the <code>.gitignore</code> file. The <code>.gitignore</code> usually is in the root of your Git project.</p> <p>An example of the patterns your <code>.gitignore</code> may contain</p> <pre>*.a build/ doc/*.txt doc/**/*.txt !doc/todo.txt</pre> <p>The meaning of the patterns:</p> <ul> <li><code>*.a</code> ignore files with extension <code>.a</code></li> <li><code>build/</code> ignore all contents of the <code>build</code> directory</li> <li><code>doc/*.txt</code> ignore all files with extension <code>.txt</code> inside of the <code>doc</code> directory</li> <li><code>doc/**/*.txt</code> ignore all files with extension <code>.txt</code> inside of the <code>doc</code> directory and all sub-directories of <code>doc</code></li> <li><code>!doc/todo.txt</code> do not ignore <code>todo.txt</code></li> </ul> <p>The <code>.gitignore</code> file itself should be under version control – so be aware of not putting <code>.gitignore</code> as a pattern into the <code>.gitignore</code> file.</p> <h2 id="branch-to-isolate">Branch to isolate</h2> <p>Any contents in Git must be in a branch. The first branch of a Git repository is the <em>master</em> branch. Technically it is a branch like all other branches, but conceptually it is the primary, stable version of whatever is stored in the repository.</p> <p>A commit will always be done inside of a particular branch. But while commits point to the past, a branch is a concept for the future. A branch is a virtual copy of your project, where commits can be made freely in isolation from whatever else may happen in the repository. You would create a branch to experiment with some new feature inside of your project, to fix a bug or to do other things which you want to have separated from everything else until you have indeed found what you are after in your branch.</p> <p>While you can have multiple branches in your repository, there is always exactly one working branch in your local repository, which is the one you are currently working on. This is what is in your <em>working directory</em> or <em>working copy</em>. Any commit you make will be against the working branch.</p> <p><code>git branch &lt;branch-name&gt; [&lt;commit&gt;]</code> will create a new branch for you. Choose a short descriptive branch name. The optional <code>&lt;commit&gt;</code> specifies a commit to start from. If you don´t give the <code>&lt;commit&gt;</code>, the branch will be created from the latest commit in the current branch.</p> <figure> <img src="https://ulf.codes/i/blog/git_new_branch.jpg" /> <figcaption>Figure: Creating a new branch with the name 'lazyload'</figcaption> </figure> <p><code>git branch &lt;branch-name&gt;</code> will not make the newly created branch your current working copy; therefore your next commit would not be against the new branch. To make the new branch the active working copy, you need to <code>git checkout &lt;branch-name&gt;</code> after you have created your branch. Whatever you commit from that point on will be inside of your new branch and nowhere else.</p> <p>Again, there is a shorthand command for creating a branch and making it the current working copy all at once: <code>git checkout -b &lt;branch-name&gt;</code> will create a new branch and make it the current working copy.</p> <figure> <img src="https://ulf.codes/i/blog/git_branch_first_commit.jpg" /> <figcaption>Figure: First commit in the 'lazyload' branch</figcaption> </figure> <figure> <img src="https://ulf.codes/i/blog/git_branch_first_commit_alternate.jpg" /> <figcaption>Figure: Alternate picture for the first commit in the 'lazyload' branch</figcaption> </figure> <figure> <img src="https://ulf.codes/i/blog/git_branch_multiple_commits.jpg" /> <figcaption>Figure: Multiple commits in the 'lazyload' branch</figcaption> </figure> <p><code>git branch [-a|-r]</code> without any option this command will show you the current list of local branches with a <code>*</code> in front of the currently active branch. Local branches are the branches you are working on and where your commits go against. With <code>-r</code> the <em>remote tracking branches</em> will be shown. <code>-a</code> will show all local branches and all remote tracking branches.</p> <p>Remote tracking branches are all branches from your remote server (please refer to <a href="#working-with-remotes-to-share-with-a-team">Working with remotes to share with a team</a>) which came with your most recent <code>git fetch</code> or <code>git pull</code> into your local repository (so they are called remote tracking, but indeed they are stored in your local repository). They are used to connect your work with a remote repository. Whenever you call <code>get status</code> and get a result like</p> <pre>Your branch is ahead of 'origin/&lt;branch-name&gt;' by 1 commit. (use "git push" to publish your local commits)</pre> <p>Git has figured out a difference between your local branch and its counterpart, the remote tracking branch.</p> <p>Remote tracking branches are named <em>origin/&lt;branch-name&gt;</em>. Don´t checkout such a branch via <code>git checkout origin/&lt;branch-name&gt;</code> – instead, do <code>git checkout &lt;branch-name&gt;</code> to make the remote tracking branch a local branch.</p> <p>To see the history of commits in a branch-oriented tree format, use <code>git log --graph --oneline</code>.</p> <p>The <code>--graph</code> option will produce the branch tree, and the <code>--oneline</code> option leads to each commit being displayed in a single line of the tree structure.</p> <h2 id="compare-your-working-directory">Compare your working directory</h2> <p><code>git diff</code> will indicate the differences between your working directory and your staging area.</p> <p><code>git diff [&lt;branch-name or commit]</code> compares your working directory with <code>&lt;branch-name or commit&gt;</code>.</p> <p><code>git diff &lt;older-commit&gt; &lt;newer-commit&gt;</code> will indicate the differences between the two commits.</p> <p>I find myself now and then using one of the two options <code>--stat</code> or <code>--color-words</code> in conjunction with any of the above <code>git diff</code> commands.</p> <p><code>--stat</code> will display a little statistic of changed files with numbers of lines added and removed.</p> <p><code>--color-words</code> will indicate changes in files word by word, instead of line by line, which is the default.</p> <h2 id="merge-to-include">Merge to include</h2> <p>Sometimes the work which has been done in a branch will be thrown away. You delete the branch, and everything is as if the branch never existed. If you don´t want to throw away your work, you probably have to bring the contents of your branch into the master branch. That´s what merge is for. All commits that have been made in your source branch have to be merged into your master branch.</p> <p>To merge any branch into your master branch, you have to</p> <pre>git checkout master git merge &lt;source-branch-name&gt;</pre> <p>The first command will bring you into the master branch; the second command will pull in the changes from the source branch into the master branch. The principle is always the same – make the branch into which you want to merge the working copy and then pull changes from any other branch into your working copy by</p> <pre>git checkout &lt;destination-branch-name&gt; git merge &lt;source-branch-name&gt;</pre> <p>To be more precise, all commits from your source branch will be merged into your working copy, which is the checked out branch.</p> <p>The simplest kind of merge is if nothing had been changed in the destination branch while you were working inside of the source branch.</p> <figure> <img src="https://ulf.codes/i/blog/git_fast_forward.jpg" /> <figcaption>Figure: Fast-forward merge of 'lazyload' into 'master' branch</figcaption> </figure> <p>In this case, any changes made in the source branch will entirely be added to the destination branch, which is called <em>fast-forward</em>. The tip (last commit, or head commit) of the destination branch and the tip of the source branch will point to the same commit then, which is the last commit that was made in the source branch. After that, both branches, the source branch and the destination branch, are identical except in their branch names.</p> <p>A <em>true merge</em> is something different. That´s when both, the source branch and the destination branch, have been modified before merging.</p> <figure> <img src="https://ulf.codes/i/blog/git_true_merge.jpg" /> <figcaption>Figure: 'master' and 'lazyload' have been modified – a true merge is needed</figcaption> </figure> <p>A fast-forward then is no longer possible, and Git has to figure out the combined state of the content, which will lead to a so-called <em>merge commit</em>.</p> <figure> <img src="https://ulf.codes/i/blog/git_merge_commit.jpg" /> <figcaption>Figure: After a true merge of 'master' and 'lazyload' a merge commit was created</figcaption> </figure> <p>Each changed file in each branch is compared. When Git identifies a line that has changed in either branch, that line is carried forward for inclusion in the destination merge.</p> <figure> <img src="https://ulf.codes/i/blog/git_merge_line_by_line.jpg" /> <figcaption>Figure: A true merge goes line-by-line</figcaption> </figure> <p>As long as the branches don´t both contain changes to the same line, Git will merge and commit automatically with a generated commit message: <code>Merge branch '&lt;source-branch-name&gt;' into '&lt;destination-branch-name&gt;'.</code></p> <p>Unlike a regular commit, which has one parent commit, a merge commit has two parent commits.</p> <p>Now, when two modified lines of the same file are overlapping during a merge, a <em>merge conflict</em> occurs. Git can not automatically solve this conflict. Instead, Git indicate the conflict in the console</p> <pre>CONFLICT (content): Merge conflict in &lt;conflicting-file-name-in-destination-branch&gt; Automatic merge failed; fix conflicts and then commit the result.</pre> <p>and put a <em>conflict marker</em> into the file of the destination branch, indicating the conflicting lines.</p> <pre>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD &lt;conflicting content line in destination-branch (the current working copy)&gt; ======= &lt;conflicting content line in source-branch&gt; &gt;&gt;&gt;&gt;&gt;&gt;&gt; &lt;destination-branch-name&gt;</pre> <p>To resolve the conflict, this entire section, including the angle brackets, needs to be edited and refactored into the final version you want to see in the file. After that, you can commit the merge with <code>commit -am "your merge commit message"</code>.</p> <h2 id="remove-or-rename-a-branch">Remove or rename a branch</h2> <p>Sometimes you want to remove a branch, e.g., after all work is done and the branch has been merged into the master. In order to go ahead, use <code>git branch -d &lt;branch-to-delete&gt;</code> to remove your local branch. To remove a remote branch (refer to <a href="#working-with-remotes-to-share-with-a-team">Working with remotes to share with a team</a>), use <code>git push origin --delete &lt;branch-to-delete&gt;</code>.</p> <p>A rename of the current local branch can be achieved by <code>git branch -m &lt;new-branch-name&gt;</code>.</p> <p>To have the renamed branch on the server, do</p> <pre>git push origin &lt;new-branch-name&gt; git push origin --delete &lt;old-branch-name&gt;</pre> <p>the second push with the <code>--delete</code> option will remove the old branch from the remote.</p> <h2 id="rewind-your-work">Rewind your work</h2> <p>The <code>git checkout</code> can not only be used to checkout an entire branch to drive further the work in this separate branch. <code>git checkout</code> is also a way to go back to the history of your work.</p> <p><code>git checkout &lt;commit hash&gt;</code> will set your working directory into the state of the commit referred to with the commit hash (the code you see for each entry in the <code>git log</code>, something like c04ff32). You are working then in the so-called <em>detached HEAD</em> state. Git will inform you about <em>detached HEAD</em> with the following output:</p> <pre>$ git checkout c04ff32 Note: checking out 'c04ff32'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b &lt;new-branch-name&gt; HEAD is now at c04ff32... New image for git committing over time</pre> <p>Another way to use <code>git checkout</code> is to use it for files.</p> <p><code>git checkout &lt;pathspec&gt;</code> will bring the file which is described by <code>&lt;pathspec&gt;</code> from the head of your current branch back into your working directory. This is useful to revert changes you did on a file while keeping the changes of other files you just modified in your working directory.</p> <h2 id="working-with-remotes-to-share-with-a-team">Working with remotes to share with a team</h2> <p>The Git working mode is offline by default. This is nice because you don´t need to have an account to sign in somewhere, you can start working with your repository.</p> <p>A remote in the Git world is a physical copy of a repository. It may be on the same computer as the repository it was copied from (copying is named <em>cloning</em> in Git) or on a different computer far away. The essential part is, you can exchange data between the two repositories and keep them synchronized. Usually, a remote repository is placed on a server which is accessible by your team. Any new teammate initially will clone the repository from the server to his or her local machine. The Git name for this remote repository is usually <em>origin</em>. The origin has nothing special and is not distinct from the local repositories on the machines of each team member, except only by convention it is used as a hub to which the team members connect to synchronize their work with all others. This will happen in a way that team members are working locally on their own computers and eventually sync with the remote repository on the hub server by <em>pulling</em> and <em>pushing</em> committed content.</p> <figure> <img src="https://ulf.codes/i/blog/git_hub.jpg" /> <figcaption>Figure: Origin is a hub by convention</figcaption> </figure> <p>Remote repositories are usually <em>bare</em> repositories, they have no staging area and no working copy like local repositories because no one is working directly on the remote repository. To indicate a bare repository usually <em>.git</em> is being appended to the name of the repository.</p> <p>A remote may be on <a href="https://github.com">GitHub</a> or on a self-hosted system you want to use as a hub.</p> <h2 id="clone-a-remote-repository-to-local">Clone a remote repository to local</h2> <p>On your local machine move to the folder under which the remote repository should be cloned <code>cd /path/to/parent/</code>. Then clone the remote repository into the parent <code>git clone &lt;repo&gt; [&lt;new-folder-name&gt;]</code>.</p> <p><code>&lt;new-folder-name&gt;</code> is the optional folder name of the cloned project on your computer.</p> <p><code>&lt;repo&gt;</code> is the path to the remote repository and has one of the following structures, each standing for a different protocol:</p> <pre>/path/to/repo.git ssh://[user@]host.xz[:port]/path/to/repo.git git://host.xz[:port]/path/to/repo.git http[s]://host.xz[:port]/path/to/repo.git</pre> <p>The first protocol is the <em>local</em> protocol. This is useful if the remote repository will reside on a shared filesystem to which every team member has access. The other protocols are obviously <em>ssh, git</em> and <em>http</em>. To learn more about these, please refer to <a href="https://git-scm.com/book/tr/v2/Git-on-the-Server-The-Protocols">“Git on the server – the protocols”</a>.</p> <p>Sometimes you try to access a server via https, and the server is using a self-signed certificate. Git won´t accept this certificate but if you are sure about the server, for example, because the server is located in your local intranet, one possible solution is the following configuration in Git:</p> <pre>cd /path/to/your/repo git config http.sslVerify false</pre> <p>As a global setting for your entire Git: <code>git config --global http.sslVerify false</code>.</p> <p>Once you have cloned the remote to your computer, Git already configured the <em>origin</em> for your project. You can check that by</p> <pre>cd /path/to/parent/&lt;repo&gt; git remote -v</pre> <p>which will display the <em>fetch</em> and <em>push</em> addresses being bound to the symbolic name <em>origin</em>.</p> <h2 id="push-data-to-remote">Push data to remote</h2> <p>If you are working on your local project and committed your changes to a branch you want to bring to the remote repository now; the general Git command format is <code>git push &lt;remote&gt; &lt;remote-branch-name&gt;</code>. This will push the contents of the local branch, your current working copy, into the <code>&lt;remote-branch-name&gt;</code> on the remote repository.</p> <p>Assuming you worked on a branch named <em>lazyload</em> and are currently on that local branch, your command is <code>git push origin lazyload</code>.</p> <p>As already mentioned, remote repositories do not have working copies or staging areas and no humans who will resolve merge conflicts. Therefore, if you push to a remote and Git can not merge with a simple <em>fast-forward</em>, Git will reject the push. The situation needs to be fixed by pulling down the changes from the remote and then trying to push again.</p> <p>The local branch names and the remote branch names are not related in Git. Even though they share the same name, Git doesn´t know that they logically represent the same piece of work. Therefore in each push, you have to tell Git to what branch on the remote you want to push. You can configure each local branch of your Git to <em>track</em> its remote counterpart. Once you have done it for a branch, you can push and pull against the remote just by typing <code>git push</code> and <code>git pull</code> without further specifying the remote and remote branch name.</p> <p>Specify the tracking with <code>git push -u origin lazyload</code> or, generally <code>git push -u &lt;remote&gt; &lt;remote-branch-name&gt;</code>.</p> <p><code>-u</code> (alternatively <code>--set-upstream</code>) is the option which will set up the tracking relationship between your current local branch and the remote branch. You only need to do it once per local branch.</p> <p>A particular case of pushing is to remove a branch from the remote, as the removing of the local branch doesn´t remove the branch on the remote. The command goes <code>git push origin --delete &lt;remote-branch-name&gt;</code>.</p> <h2 id="pull-data-from-remote">Pull data from remote</h2> <p>If you want to get the latest changes, e.g. from the <em>lazyload</em> branch on the remote repository, into your local branch, call <code>git pull origin lazyload</code> or, in general, <code>git pull &lt;remote&gt; &lt;remote-branch-name&gt;</code>.</p> <p>Git will automatically merge the remote changes into your local branch. In case of a merge conflict, resolve the conflict marker in your local branch, stage, commit your change and push to the remote.</p> <h2 id="the-big-picture">The big picture</h2> <figure> <img src="https://ulf.codes/i/blog/git_big_picture.jpg" /> <figcaption>Figure: Git commands and their fields of operation</figcaption> </figure> <h2 id="command-reference">Command reference</h2> <p>The following list is by far not complete. Though I found myself using these commands and options most often. For a complete list please refer to <a href="https://git-scm.com/docs/">git-scm.com/docs/</a>.</p> <h3>Create new local repo</h3> <pre>cd /path/to/your/prj/ git init</pre> <h3>Copy existing repo</h3> <pre>cd /path/to/parent/ git clone &lt;repo&gt; [&lt;new-folder-name&gt;]</pre> <p>Where <code>&lt;repo&gt;</code> is one of</p> <pre>/path/to/repo.git ssh://[user@]host.xz[:port]/path/to/repo.git git://host.xz[:port]/path/to/repo.git http[s]://host.xz[:port]/path/to/repo.git</pre> <p>Watch out</p> <pre>git config [--global] http.sslVerify false</pre> <p>as one possible solution in case Git doesn´t allow you to connect to a repo via https.</p> <h3>Status of repo</h3> <pre>git status</pre> <h3>Stage content</h3> <pre>git add &lt;pathspec&gt;</pre> <p>or</p> <pre>git add --all</pre> <p>to un-stage, use</p> <pre>git reset &lt;pathspec&gt;</pre> <h3>Removing files which have not been staged</h3> <pre>git clean [-ifd]</pre> <h3>Commit content</h3> <pre>git commit [-a] [-m "your commit message"]</pre> <p>where <code>-a</code> will stage all modified and deleted content and <code>-m</code> indicates the commit message, alternatively</p> <pre>git commit -am "your commit message"</pre> <h3>See history of commits</h3> <pre>git log [--oneline] [--pretty] [&lt;branch-name&gt;]</pre> <h3>Remove file</h3> <pre>git rm &lt;pathspec&gt;</pre> <h3>Rename file</h3> <pre>git mv &lt;current-path&gt; &lt;new-path&gt;</pre> <h3>Ignore file</h3> <p>Use one pattern per line in .gitignore file</p> <pre>*.a build/ doc/*.txt doc/**/*.txt !doc/todo.txt</pre> <h3>See what branch you are on</h3> <pre>git branch [-a|-r]</pre> <h3>Create a branch</h3> <pre>git branch &lt;branch-name&gt; [&lt;commit&gt;]</pre> <p>or</p> <pre>git checkout -b &lt;branch-name&gt;</pre> <p>to create and checkout the branch.</p> <h3>Checkout a branch</h3> <pre>git checkout &lt;branch-name&gt;</pre> <h3>Compare changes</h3> <pre>git diff [--stat] [&lt;branch-name or commit&gt;] git diff &lt;older-commit&gt; &lt;newer-commit&gt; </pre> <h3>Merge</h3> <pre>git checkout &lt;destination-branch-name&gt; git merge &lt;source-branch-name&gt; </pre> <h3>Rename a branch</h3> <pre>git -m &lt;branch-name&gt;</pre> <h3>Delete a branch</h3> <pre>git -d &lt;branch-name&gt;</pre> <h3>Activate an older commit</h3> <pre>git checkout &lt;commit-hash&gt;</pre> <h3>Discard file changes</h3> <pre>git checkout &lt;pathspec&gt;</pre> <h3>Push to server</h3> <pre>git push [-u] &lt;remote&gt; &lt;remote-branch-name&gt;</pre> <p>to push from current branch to remote branch, where <code>-u</code> can be used once to track the remote branch from the current branch. After setting the upstream with <code>-u</code>, it can be pushed and pulled from the current branch without specifying <code>&lt;remote&gt;</code> and <code>&lt;remote-branch-name&gt;</code>.</p> <h3>Pull from server</h3> <pre>git pull &lt;remote&gt; &lt;remote-branch-name&gt;</pre> <p>to pull from remote branch into current branch. If remote branch tracking has been activated before via <code>-u</code> in a <code>git push</code>, it can be pulled from the remote branch without specifying <code>&lt;remote&gt;</code> and <code>&lt;remote-branch-name&gt;</code>.</p> <h3>Tell Git who you are</h3> <pre>git config [--global] user.name ["your name or user name"] git config [--global] user.email ["your email address"]</pre> <h3>Display your Git config</h3> <pre>git config --list</pre> <h3>Edit your Git config file</h3> <pre>git config [--global] --edit</pre> <h3>Configure your editor</h3> <p>Set your editor</p> <pre>git config --global core.editor &lt;editor-name&gt;</pre> <p>Display your current editor setting</p> <pre>git config core.editor</pre> <h3>Let Git accept your self-signed certificate</h3> <pre>git config [--global] http.sslVerify false</pre> <h2 id="references">References</h2> <dl> <dt>[Atlassian Git]</dt> <dd>“Getting Git Right”, Altassian Git Tutorial, <a href="https://www.atlassian.com/git/">atlassian.com/git</a></dd> <dt>[Bash Git Completion]</dt> <dd>“Install Bash Git Completion”, <a href="https://github.com/bobthecow/git-flow-completion/wiki/Install-Bash-git-completion">github.com/bobthecow/git-flow-completion/wiki/Install-Bash-git-completion</a></dd> <dt>[Beams 2014]</dt> <dd>C. Beams, “How to Write a Git Commit Message”, 2014, <a href="http://chris.beams.io/posts/git-commit/">chris.beams.io/posts/git-commit</a></dd> <dt>[Caching Your Git Password]</dt> <dd>“Caching your GitHub password in Git”, <a href="https://help.github.com/articles/caching-your-github-password-in-git/">help.github.com/articles/caching-your-github-password-in-git/</a></dd> <dt>[Chacon, Straub 2014]</dt> <dd>S. Chacon, B. Straub, “Pro Git”, 2014, <a href="https://git-scm.com/book">git-scm.com/book</a></dd> <dt>[Cheat Sheet]</dt> <dd>“Git Cheat Sheet”, <a href="https://www.git-tower.com/blog/git-cheat-sheet/">www.git-tower.com/blog/git-cheat-sheet/</a></dd> <dt>[Demaree 2016]</dt> <dd>D. Demaree, “Git for Humans”, A Book Apart, 2016, <a href="https://abookapart.com/products/git-for-humans">abookapart.com/products/git-for-humans</a></dd> <dt>[GitHub]</dt> <dd>“Welcome home, developers”, <a href="https://github.com">github.com</a></dd> <dt>[GitHub Desktop]</dt> <dd>“Simple collaboration from your desktop”, <a href="https://desktop.github.com">desktop.github.com</a></dd> <dt>[GitRef]</dt> <dd>Git command reference, <a href="https://git-scm.com/docs/">git-scm.com/docs/</a></dd> <dt>[Git]</dt> <dd>Git downloads for different platforms, <a href="https://git-scm.com">git-scm.com/downloads</a></dd> <dt>[Learn]</dt> <dd>“Learn Git &amp; Version Control”, <a href="https://www.git-tower.com/learn/">www.git-tower.com/learn/</a></dd> <dt>[Tower]</dt> <dd>Version control with Git – made easy, In a beautiful, efficient, and powerful app, <a href="https://www.git-tower.com">git-tower.com</a></dd> <dt>[Westby 2014]</dt> <dd>E. J. Westby, “Dealing with Emergencies in Git”, 2014 <a href="https://24ways.org/2014/dealing-with-emergencies-in-git/">24ways.org/2014/dealing-with-emergencies-in-git/</a></dd> </dl> Sat, 23 Apr 2016 00:00:00 +0000 https://ulf.codes/thoughts/pocket-git-guide/ https://ulf.codes/thoughts/pocket-git-guide/thoughts Spitfire <p>Spitfire is a virtual whiteboard to be shared by multiple persons at the same time. Users will be anonymous – so no one needs to sign in.</p> <p>Spitfire can be used as a simple task board, in agile retrospectives or brainstorming sessions, quietly whenever teams are working across different locations and want to have immediate feedback on content change.</p> <figure> <img alt="Image of Spitfire tool" src="https://ulf.codes/i/spitfire/spitfire.jpg" /> </figure> <p>Go to <a href="http://spitfire.peewee.space">spitfire.peewee.space</a>, create a whiteboard session, and share the URL with the people you want to work with. Anyone who has access to that URL can participate in your work.</p> <p>Spitfire is free to use for everyone. I am building it on top of the <a href="http://www.meteor.com">Meteor</a> platform while obeying the agile mantra: <em>Make the simplest thing that will possibly work now. Validate. Repeat. Yay.</em> Spitfire is Open Source. Find the code on <a href="http://github.com/ulfschneider/spitfire">GitHub</a>.</p> Thu, 20 Aug 2015 00:00:00 +0000 https://ulf.codes/tools/spitfire/ https://ulf.codes/tools/spitfire/tools Supersize <p>Do not let scaled agile be your scaled snake oil</p><p>We have to scale agile when more than one team is required to get a thing delivered. Each team, not more than ten members. There will be adjacent topics which belong to an agile organization, but when we focus just on delivery, that´s it: multiple teams working on one thing.</p> <p>Agile is about culture and cultural change. Scaling agile means radically, to scale cultural change. This is an incredibly difficult thing to do. Peter Drucker coined the phrase <em>“culture eats strategy for breakfast”</em>. You better prepare for the long run. Is it clear, why you want to change? <em>You</em> are: managers, who define how the system works, product managers who determine what kind of product to build, research and development people who explore possibilities, engineers who make the product, salesforce who will drive sales, project managers who are in charge of leading one-of-a-kind endeavors – you will identify even more people and roles for your organization.</p> <p>Do your leaders have a sense of urgency that agile is the way to go? Can they argue for it and will they? Do your leaders know what problem they want to solve by being agile?</p> <p>You have to change, you know that because the first rule of life is <em>adapt or die</em>. Do you think it can happen by implementing some new release train processes that you have seen in the latest scaled agile book? Or disseminating a slide deck to your subordinates, giving the order to work in Sprints and counting Sprints as being unsuccessful if some tasks are left undone at the end of the Sprint? By letting the Project Management Office give instructions to standardize Scrum Boards in the entire company with predefined columns? Or printing sticky note templates to have them all look the same on the boards, without referring to your workforce? These top-down communications are patterns of how to get agile wrong. If you think this is scaled agile and will lead to cultural change, then you are heading for scaled snake oil. Mentally, your people will step aside and identify the entire thing as some theater communication. If you understand agile as the current way of working to only squeeze more results faster out of your knowledge worker people, because your engineered waterfall projects seem to fail too often without delivering the desired outcome, you did not get the idea of agile.</p> <p>Agile is not implementing a process and then follow. Agile has to be earned, not given.</p> <h2 id="every-organization-is-unique">Every organization is unique</h2> <p>Though, every organization is unique and has to find answers to questions like “what delivers value?”, “What is a success?”, “How would we know we achieved success?” and, of course, “Why to be agile?” and “What does it mean to be agile?” – there are some general properties which I believe characterize agile organizations.</p> <h2 id="agile-properties">Agile properties</h2> <p>Find out, if this is something for you: Center around people and results, not processes. Processes are servant, not master. Still, continuously improve processes and focus less on improving the monitoring of people. Identify what brings value to your customers and organize around delivering that value. Money is not the goal; it is a result which comes from achieving value for delighted customers. Have a straight line from your product strategy to your release strategy to the delivery order of the features within a release. Things are ordered in a way to deliver the highest value first, in small increments regularly. The people are oriented about that and understand. Transparency on all levels with everyone seeing the same figures, whether it´s the progress of value delivery or costs and earnings. The workforce is emancipated and authority is brought to where information lives and not information is brought via monitoring chains to “authorities”. Give control to people and not take control. Decentralize and find ways to let information and energy flow smoothly to the places where needed. Be clear about the goals and intent, but leave space for the workforce to find ways how to achieve the goals. Grow competency to perform.</p> <p>Strive for a learning attitude on all levels to enable the organization to get better and to lead change. Team and personal growth are not only lip service and to be a leader is about duties and responsibilities and not necessarily about privileges. Leaders are cultivators rather than controllers [Mayer 2013:63]. Instead of one-way, top-down commanding communication, the horizontal discursive approach is the default. Top-down is only used where needed. This organization is more of a leader-leader type instead of playing the leader-follower game (compare with [Marquet 2013]). You want leaders on all levels and not people with their brains off and only following given procedures.</p> <p>The agile organization is a failure resilient, success-seeking, cooperative, status quo challenging, potential growing, knowledge worker organization. It is not a failure avoiding routined good behavior following procedures company.</p> <h2 id="not-for-mummys-boys">Not for mummy´s boys</h2> <p>You may want to “use” agile only for a single project with 8, 20 or even 50 people and don´t think about your entire organization at first hand. That is ok, growing natural makes sense, and to understand how things work in the small and then scale, will give some chance for any scaling endeavor to function. Chances are, you try to go the agile way because your project currently is about to sink. This may also work because then you have some pressure for clarity and right decisions – but no guarantee that you will make the right decisions of course.</p> <p>Now, even being agile in a team of 8 people is incredibly difficult if you haven´t done it before. It is likely the most disciplined way of working you ever had to, or, better, wanted to achieve in your work life. It is not easy going. You have to be unafraid and explore. But it is not all hard stuff, it is mostly about people and purpose and real collaboration, about engagement, choice, and fun at work, about trust, freedom, ownership and a sense of self [Mayer 2013:29]. I suppose no one ever achieved something great only because it was told him to do. You can achieve great if you see a purpose, if you are convinced, if you reinforce the spirit of your team, by making and learning, making and learning. As managers, you can not buy such behavior and attitude, nor can you give orders to do so. You have to set suitable constraints to give self-organizational forces a direction and give people the authority to act like human beings. Be prepared to learn and adapt, because you will have to.</p> <p>That said, why would you want to do that? Isn´t it better for the organization to be robust, reduce room for surprise and have people following orders?</p> <p>I can identify four angles to assess the topic: the market, the problem class, the process model and the people.</p> <h2 id="market">Market</h2> <p><em>Remark:</em> The following paragraphs on <em>market</em> have been taken from the text <a href="https://ulf.codes/art-in-work">“The art in our work”</a>.</p> <p>The centralized planning, disassembly, and automation of work brought us to the integration of human labor into precise production timing and to an understanding of companies as automatic production machines. Wohland and Wiemeyer explain the concept with their model of the Taylor-Tub.</p> <figure> <img src="https://ulf.codes/i/blog/taylor_tub.jpg" /> <figcaption>Figure: The Taylor-Tub [Wohland and Wiemeyer 2007:23]</figcaption> </figure> <p>In the Taylor-Tub the thoughts of the individual are not of importance, because all workflows, procedures, and processes are already defined upfront and have to be followed. This makes the system robust, but inflexible. We have been educated for this world of working, which means we have been taught to follow. This brought up disruptive productivity growth and inert mass markets during the last century. The biggest problem to solve for these markets: how to produce as much as possible at the lowest price.</p> <p>Today’s markets are more and more characterized by their narrowness and/or complexity. This complexity requires a better understanding of customer needs, higher flexibility and often interdisciplinary approaches. Those companies that can create and live up to such dynamics, the top performers, set the less capable companies under pressure. The biggest problem to solve for these markets: how to connect to the customer, identify what delivers real value and be able to do it fast. Companies that can not create the dynamics will suffer the pressure.</p> <p>The necessary momentum is being created by dynamic people, by experienced and skilled workers who responsibly and self-organizing produce results – people who can bear with complexity. For those people, values and leadership are of much higher importance than centralized control and management.</p> <p>Agile values support dynamic and skilled knowledge workers. For your organization to be able to cope with current market requirements, you may be forced into an agile working style, whether you like it or not.</p> <h2 id="problem-class">Problem class</h2> <p>Any innovative endeavor will challenge knowledge workers with uncertainty about the problem space and the suitable solution space. To pick up a slightly modified Stacey Matrix, it is this uncertain complexity space where knowledge workers are at home, and that´s where agile is positioned.</p> <figure> <img src="https://ulf.codes/i/blog/uncertainty.jpg" /> <figcaption>Figure: The complex problem class is characterized by uncertainty, this is the place where agile is at home</figcaption> </figure> <p>In this complex area, we talk about dynamic, self-organizing systems with non-linear behavior — an environment, where more is unknown than known. The apriori definition of all states of which the system can be in – and how to move the system from any of these states into a desired other state — is not possible. One has to work through this environment to get a grip on it. Therefore the apriori definition of a detailed step-by-step execution process will not function and to put more effort into upfront planning will only consume more energy but won´t improve the outcome.</p> <p>This leads to the next, tightly coupled angle on the agile topic: the process model to use.</p> <h2 id="process-model">Process model</h2> <p>Being positioned in dynamic, competitive markets that are characterized by uncertainty of both, problem space and solution space, we have to ask for a suitable process model to support and guide the workforce to achieve results. The detailed upfront planning of execution steps, the defined process model, does not bring any advantage, instead even the disadvantage of false safety and effort consumption. The waterfall process follows such a defined process model.</p> <figure> <img src="https://ulf.codes/i/blog/waterfall.jpg" /> <figcaption>Figure: The waterfall process follows the defined process model approach</figcaption> </figure> <p>Consider the following questions:</p> <ol> <li>You already spent 30% of your available time and effort and just finished your design phase. Are you 30% done? Probably you can´t tell, because you are sitting on a stack of unvalidated paper. No working code.</li> <li>Do you have something of value for your customer or yourself? Can your customer do something with your paperwork? I assume not, again, only a stack of unvalidated paper. Reality will correct that when you start to write working code.</li> <li>Let´s say you learn during your implementation phase and something has to be reworked which makes a design change necessary. Will you proceed a change request? How long will you try to avoid it? Usually, a change request in the waterfall process is treated like a failure which is being sought to circumvent as long as possible. That´s why change requests are so expensive in this process model. And that´s why learning is so costly in the waterfall process.</li> </ol> <p>In the agile world, we respond with the empirical process model.</p> <figure> <img src="https://ulf.codes/i/blog/iterations.jpg" /> <figcaption>Figure: The iterative process follows the empirical process model approach</figcaption> </figure> <p>Working in short iterations of 1, 2, 3 or 4 weeks long and delivering working software at the end of each iteration will give you the security net that is comparable to what mountain climbers do when they climb and secure, climb and secure. At the end of each iteration, you reach a safety point that tells you what is and what not.</p> <p>Picking up the same questions I already asked for the defined process model:</p> <ol> <li>If you have spent 30% of your time and effort, you can accurately compare that with the list of already done pieces of software. Your measurement for progress is no longer spent effort or time, but done work compared to missing pieces yet waiting to be delivered. This is clear and simple. Possibly you are 30% done at that point. Your customer decides, and you can tell him exactly what is done.</li> <li>Do you have something of value for your customer or yourself? You should. If you have build working software in each iteration, even if not delivered to the customer, you have something to show and to learn from and to rely on.</li> <li>Now you learned something after 30% of your effort is spent (of course, you did even before). Can you change direction quickly? Probably, because after each iteration you can decide what the next most important move is and go ahead while delivering software. <em>And I have two additional questions:</em></li> <li>Is it difficult to work this way? Of course. The team has to master the culture shift to deliver done software by following the value and completing the stuff that brings the most value first. Also, the technical skills of the team have to grow to support this agility. Without automatic tests and automatic build of software in short intervals, you won´t get there. All your systems need to be aligned towards giving feedback as fast as possible.</li> <li>Will this way of working help you to deliver appropriate results? Sure. Feedback and learning are an inherent part of this model. This responds directly to the uncertainty of the complex problem class that you are in. To deal with a world where more is unknown than known requires us to <em>“cut through the noise by taking action”</em> [Beedle and Schwaber 2002:27] and continuously validate our mental models against reality – as we go.</li> </ol> <h2 id="people">People</h2> <p>In this short enumeration from the market over problem class to the process model, the last mentioned is the people. Last, not least. People are the most important. Everyone counts, it is no longer that people are being told what to do and follow. With the follower mental model, you will not survive in dynamic, competitive markets or complex problem situations. The only way to survive is with dynamic leaders at all levels in the organization; people who explore problem and solution spaces and find ways to achieve things, artists, status quo challengers with excellent skills. These people have the drive to achieve and strive for purpose, autonomy, and mastery. Of course, in job advertisements, all companies seek for this kind of folks, but after the hiring process, in the “real life”, these talents are being treated like if they were all the same and interchangeable, average, like resources, often without any sense and respect. To make it clear, the agile mindset asks for creativity, attitude, know-how, opinions, and cooperation. We want people in their entireness and give them space to grow. We want them to ask “why” and insisting on answers. I believe, everyone in current corporate structures has the ability and the wish to act as a whole human being, but when people are treated day-in and day-out as interchangeable resources, it doesn´t take long, and they behave accordingly, switch brains off and do something interesting in their spare time. You know – setting constraints directs self-organization!</p> <p>To sum it up, agile does help in competitive dynamic markets. It does help to solve complex problems by leveraging an empirical process model and reinforcing the self-awareness of people as whole human beings.</p> <h2 id="programmers-drive-it">Programmers drive it</h2> <p>The agile movement started in the IT industry. It is driven by programmers and engineers at first hand, by people who are in the process of making and delivering. That kind of people who know since long how hard it is to get an idea to life and build something which other people like to use (and pay for). I assume the agile mindset found its first expression in Extreme Programming and Scrum in the second half of the 1990s, followed by the Agile Manifesto in 2001. And to me, when talking about agile in terms of frameworks, still I mean Scrum + XP, I don´t see we need more.</p> <p>The ideas, values, and principles of agile are pro people and pro results. The central working unit is the team, at max ten persons, cross-functional and being able to deliver results. The team is emancipated, has authority to decide, the competency to act and clarity in the goals to achieve.</p> <blockquote> <p>Agile is about letting people make things that deliver value now while being connected to their work and validating results. The people are value focused and have the technical expertise to deliver frequently.</p> </blockquote> <p>Agile delivery goes with the least possible process that is expected to work. This process is a servant, not a master. For example, the Scrum framework can be drawn and explained on a beer coaster – which does not mean it´s easy to live up to.</p> <p>If you have not achieved this way of working for a single team in your organization, why would you believe you can overstep this level and try to work “agile” within the entire organization, in multiple locations, continents, timezones, social cultures?</p> <h2 id="transparency">Transparency</h2> <p>You don´t solve problems by making them harder to see. You have to use the fast failure that is being promoted by agile instead of hiding it under an additional process layer. A thing like <a href="http://www.scaledagileframework.com">SAFe</a> (Scaled Agile Framework) will put such layer between the delivery folks and management. It allows the management to ignore change and see the world as they have always seen it – only with a different decoration. And yet (or because of), there is a market for this kind of stuff. SAFe is not alone, to get an impression I´d like to point you to this <a href="http://ronjeffries.com/articles/2015-07-07-yet-another-method/">article</a> by Ron Jeffries. One of the “best” scaling frameworks is the <a href="http://www.lafable.com">LAFABLE</a> process, which <a href="http://www.mountaingoatsoftware.com/blog/introducing-the-lafable-process-for-scaling-agile">Mike Cohn</a> introduced on the 1st of April 2014.</p> <p>Even the simple Scrum framework, in the wrong hands or misunderstood, so that the enforced transparency is used to take control over the team, will lead to micromanagement and annoyed developers.</p> <p>Ken Schwaber once suggested using a transition team to address the organizational change which is being demanded by the delivery units [Schwaber 2007].</p> <figure> <img src="https://ulf.codes/i/blog/transition_team.jpg" /> <figcaption>Figure: Transition team</figcaption> </figure> <p>As managers, you don´t need to invent new structures upfront – the agile delivery teams will quickly indicate the problem spots. Just pick up those indications and handle them with care. As managers, if you don´t find a way to show up for your people, to make clear that you care and are serious about agile, if you can not make it visible that you catch dysfunctions and find ways to solve problems, simply to deliver the organizational change that is needed, if you can´t do that, you can´t do agile. It is not enough to expect people to produce working and valuable software at the end of each iteration and the management does not do more than counting velocity points and staring on product burndown charts.</p> <p>Personally, if I don´t see managers dealing proactively with the dysfunctions that are indicated by the delivery folks, for example by leveraging a transition team like described by Ken Schwaber, I can´t take anything that comes from management about agile for serious. Then agile is only lip service and decoration. How would you expect the delivery people to build valuable stuff every two weeks, make everything transparent, while the management isn´t committed and organized to deliver necessary organizational change with a similar pulse?</p> <p>To implement large scaling frameworks and not to use a transition team instead is introducing “agile” (by name, not by meaning) like a waterfall (yes, with a defined process model). Start with the transition team to scale agile and invent your mechanisms and solutions. Show that you care. See what works for your organization, be self-confident and do not copy others.</p> <p>In the world of sports, when you start running, for example, it is not essential to have a pulse meter, fancy clothing and the like. Instead you only need a pair of running shoes and – of course – have fun and run regularly. When scaling agile in your organization, it´s the same. The core is to build and make things right. If you can do that in the small, in one team, think about growing larger. Learn while you are doing.</p> <h2 id="supersize">Supersize</h2> <p>Scaling agile beyond the first team is the first step of scaling. Is there an end? What size can you reach or want to achieve? How long does it take?</p> <figure> <img src="https://ulf.codes/i/blog/supersize.jpg" /> <figcaption>Supersize</figcaption> </figure> <p>The general answer is, keep it as small as possible and, again, try to find the least solution that can work. Attacking the topic from the start as a scaling endeavor will not help you. Agile will scale itself when you allow it to honestly work on a team level. Your organization will learn from such achievement and find a natural way to scale. Scaling is not the primary goal; it is a result of a curated successful agile implementation in the tiniest cells.</p> <p>The more people are included, the more communication work is imposed on the people because communication effort will grow quadratic and not linear.</p> <p>Here is the simple math: Communication lines among people grow in terms of n(n-1) (with a team size of n). By this you come to 20 communication lines for a team size of 5, 30 lines for a team size of 6 and a team with nine people will have 72 lines that need to be maintained among senders and receivers in the team.</p> <figure> <img src="https://ulf.codes/i/blog/communication_lines.jpg" /> <figcaption>Figure: Communication lines</figcaption> </figure> <p>That´s the reason for not letting a team grow beyond ten people. If more people are needed to achieve things, split into teams with reduced dependencies between each other. The best concept to minimize dependencies, we know so far, is to have cross-functional teams where each team can deliver an entire feature that makes sense to a customer, end-to-end. You then have developers, front-end, back-end, QA, UX and so on in one team – shortly everyone who needs to be there to come to a result.</p> <p>The other way around, having teams grouped by architectural components or skills, like front-end, back-end, UX and the like in separated teams, will increase dependencies and lead to teams blocking each other when delivering end-to-end features. No team alone can deliver, and the people will have to maintain not only the communication lines inside of their team but in addition to all people in other teams who are needed to deliver the feature.</p> <p>Focus on this: have a team to be able to deliver done software by the end of each iteration, always doing the most valuable things first, and let them work together as a real team. From that point on the people are in a self-carrying upwards movement. As managers you only need to move barriers out of their way, the rest they will go alone. Scaling before you reached that point will just let you scale up a mess.</p> <h2 id="standup">Standup</h2> <p>Let´s assume you do daily standups with component- or skill-formed teams (I hope you do standup´s, doing it not is a terrible idea). Considering the purpose of a daily standup is to ensure the delivery of a feature by the end of your iteration and to unhide the necessary adjustments to reach that goal; usually, a daily standup with only the people who belong to a single architectural component doesn´t support you at all. You will find communication without direction and the impression of wasting time among the participants. This is not fruitful.</p> <p>Instead, if <em>all</em> the people who deliver a feature are together from the start, a so-called cross-functional team, the standup supports collaboration and communication towards that goal of feature delivery, and the team can start to hunt features.</p> <h2 id="feature-and-component-matrix">Feature and component matrix</h2> <p>Traditionally, most teams are organized by similar skills or technical components. My suggestion is not to throw this all up in the air and try to reorganize in feature teams. Instead, it can be a method to move on step by step. Try to see the entire thing as a fluent matrix structure. This is how it goes: stick with the component teams and try to see them as some profession frame with people who keep their architectural component intact and maintain their specific professional skills. Now, also, when you have a clear backlog with a straight line from your product strategy to the delivery order of your features, pick the first and most valuable feature and let the people select themselves by deciding who is needed to deliver it. Those people will be your first feature team. Then pick your next feature from the backlog and do the same again. You will be able to identify chunks of features that should go to one feature team or the other, but the important thing is, now you have two organizational dimensions – the established that is grouped by components and skills, and the new one, which will support you to hunt for features. This is a start. Maybe over time you identify patterns, see who often comes together to deliver a feature, what is working, what not, and then you adjust. My suggestion here is only to make the first start.</p> <h2 id="conways-law">Conway´s law</h2> <p>You may have heard about the essential idea pointed out by Melvin Conway, that you replicate the structure of your organization inside of your products <a href="http://www.melconway.com/Home/Conways_Law.html">[Conway 1968]</a>. Simply, if you have a bloated, unfocused organization with unclear goals and responsibilities, your products will look the same. Instead, if you have a lean, focused organization with clear goals and responsibilities, again, this will be recognized in your products. For example, if two departments are responsible for developing a specific product, chances are, that the outcome will be made up of two components. If the two department heads cannot bear with each other, the interfaces of the two parts will not function well. In this case, you will find duplicated or missing attributes, performance issues, long durations to identify failures and so on. All that said, this doesn´t give you concrete advice how to structure your organization, but when people are getting aligned to develop a thing, keep Conway´s law in mind!</p> <h2 id="principles">Principles</h2> <p>There is no precise recipe to follow. But you can use some guiding principles that will surely support you on your journey to let an agile organization grow. I´m convinced that the <a href="http://scaledprinciples.org">ScALeD Principles</a> point in the right direction. Believe in yourself and your organization, follow the principles instead of checklists. A checklist is useful for well-defined procedures that can be analyzed upfront (I´m using the term checklist as a drop in for “scaled agile framework”). When you reinvent your organization, a list will not help. Likely it will let you switch off your mind and make you repeat things other people have thought of. In any way, embrace <a href="http://https://ulf.codes/self-organization">self-organization</a>. This force of life will give your organization the power to survive in complex environments. In an enterprise context, self-organization needs to get a direction by setting constraints. These constraints have to address two preconditions for fruitful self-organization: competency and clarity [Marquet 2013].</p> <p>Competency means the technical skills to do things on top of a craft. These skills need to be maintained and nurtured. You know, skills are bound to people.</p> <p>Clarity means clarity in organizational goals and intent. Understand what brings value and follow the value.</p> <p>Scaling agile is about emancipating people. Strive for clarity in goals and intent, let people grow their competencies and give them control to decide. Then agile is self-scaling. Focus on being agile at the team level. From there on you only need to move barriers out of the way and growth will be self-carrying into the organization.</p> <h2 id="references">References</h2> <dl> <dt>[Beedle and Schwaber 2002]</dt> <dd>K. Schwaber, M. Beedle, “Agile Software Development with Scrum”, Pearson Prentice Hall, 2002</dd> <dt>[Cohn 2014]</dt> <dd>M. Cohn, “Introducing the LAFABLE Process for Scaling Agile”, 2014, <a href="http://www.mountaingoatsoftware.com/blog/introducing-the-lafable-process-for-scaling-agile">http://www.mountaingoatsoftware.com/blog/introducing-the-lafable-process-for-scaling-agile</a></dd> <dt>[Conway 1968]</dt> <dd>M. E. Conway, “How Do Committees Invent?”, 1968, <a href="http://www.melconway.com/Home/Conways_Law.html">http://www.melconway.com/Home/Conways_Law.html</a></dd> <dt>[Jeffries 2015]</dt> <dd>R. Jeffries, “Do we really need another method?”, 2015, <a href="http://ronjeffries.com/articles/2015-07-07-yet-another-method/">http://ronjeffries.com/articles/2015-07-07-yet-another-method/</a></dd> <dt>[L.A.F.A.B.L.E]</dt> <dd>M. Cohn, “Large Agile Framework for Big, Lumbering Enterprises”, 2014, <a href="http://www.lafable.com">http://www.lafable.com</a></dd> <dt>[Marquet 2013]</dt> <dd>L. D. Marquet, “Turn the Ship Around! A true story of turning followers into leaders.”, Penguin, 2013</dd> <dt>[Mayer 2013]</dt> <dd>T. Mayer, “The People´s Scrum, Agile Ideas for Revolutionary Transformation”, Dymaxicon, 2013</dd> <dt>[Wohland and Wiemeyer 2007]</dt> <dd>G. Wohland, M. Wiemeyer, “Denkwerkzeuge der Höchstleister, Wie dynamikrobuste Unternehmen Marktdruck erzeugen”, Murmann Verlag, 2007</dd> <dt>[Schwaber 2007]</dt> <dd>K. Schwaber, “The Enterprise and Scrum”, Microsoft Press, 2007</dd> </dl> Fri, 24 Jul 2015 00:00:00 +0000 https://ulf.codes/thoughts/supersize/ https://ulf.codes/thoughts/supersize/thoughts Self-organization <p>A force of life</p><p>Self-organization is the determining element for agile teams and companies. To think and act accordingly requires the acceptance of evolutionary forces which are an inherent part of any social system, whether we like it or not.</p> <p>This contrasts with the constructing model, in which a central masterminded instance designs the system and controls it. Broadly, one can say that self-organization relies on evolution and construction relies on command and obedience.</p> <p>The affirmation of the evolutionary approach is rewarding but will challenge traditional behavioral patterns even in the microcosm of a single team. For the entire – possibly huge – organization is the paradox of giving up central control to make the organization controllable, radical and requires open minds and the willingness to learn and improve – in particular from the leaders of the organization.</p> <p>Leaders in agile organizations have the vital function of actively giving self-organizational forces a direction. This seems to be conflicting with the evolutionary approach and to span the tension field even further, here are two quotes I found in [Malik 2009:137]:</p> <figure class="breakout"> <blockquote> The only things that evolve by themselves in an organization are disorder, friction, and malperformance. </blockquote> <figcaption>Peter F. Drucker</figcaption> </figure> <figure class="breakout"> <blockquote> … the only possibility of transcending the capacity of individual minds is to rely on those super personal, 'self-organizing' forces which create spontaneous orders. </blockquote> <figcaption>Friedrich A. von Hayek</figcaption> </figure> <h2 id="past-and-present">Past and present</h2> <p>Fredmund Malik is pointing out in his work, that our current organized society developed itself during the last 150 years. In former times there were organizations, too, but they had more of an amplifying function which means that most of the people did more or less the same, e.g., shooting a weapon, transporting bricks, piling one brick on the other. In these organizations, there were only some rare specialists like master builders or officers.</p> <p>As a consequence of the visibility of tasks and clear hierarchies, the communication patterns were simple. Knowledge did not play a major role, and only some commands were needed to move the entire organization: “fire”, “heave-ho” and the like. [Malik 2009:8]</p> <p>Of course, knowledge played a role at any time in history, but we have to see this in relation to the knowledge that is needed nowadays.</p> <p>With the dawning industrialization, a new type of organization arises. Reading and writing are essential skills even for most straightforward operations. Specialists are everywhere, and not many people are doing the same things. Nearly everyone is speaking a specialized language. Knowledge and communication are essential and characteristic for this new organization. The world we live in, with engineers, computer scientists, psychologists, neurologists, marketing experts, genetic engineers and the like developed itself during the last 150 years.</p> <p>But how can this new world be connected to the evolution principle?</p> <figure class="breakout"> <blockquote>The new world is the result of humans acting, but it is not made by a central constructing instance and in this way not the result of human design. </blockquote> <figcaption>Friedrich A. von Hayek</figcaption> </figure> <p>The connection is, 150 years ago as well as today no mastermind can overview this world, to construct it and to plan it. The system organized itself in evolutionary steps.</p> <h2 id="complexity">Complexity</h2> <p>A consequence of evolution is the increase of complexity which leads to enhanced regulatory capacity. But the better organizational ability also increases chances of misregulation. That makes the steering of complex systems incredibly tricky. But on the other hand, complexity is a prerequisite for outstanding achievements. [Malik 2009:17]</p> <p>Complex systems function although no one understands the entire system. An automobile manufacturer can build a complicated and efficient car in serial production with high safety standards, although no one understands the entire construction or manufacturing process fully. A hospital is functioning although no single person knows all means and all treatment procedures.</p> <p>The central construction of such systems would be limited to centralized knowledge which immediately would become a bottleneck for the organization.</p> <blockquote> <p>It is irritating that a central instance cannot control a complex system, still, the system is self-sustaining.</p> </blockquote> <h2 id="self-organization">Self-organization</h2> <p>Self-organization describes spontaneous – emergent – processes that bring a system into some order and to sustain that order. That includes the reaction to internal and external changes, in other words, the adaptability to new conditions <a href="http://www.sbendel.ch/fileadmin/user_upload/PDF/IK_Vortrag_KFH.pdf">[Bendel 2006:2]</a>. The ability to self-organize is a property of the system even without the actors being aware of that ability. The interactions between the actors give the essential feature of the self-organizing capability.</p> <p>Water being wet is an emergent property. A single H2O molecule cannot be wet, but a lot of interdependent water molecules will develop the property of being wet.</p> <p>Pedestrians participating in crowded events will, when searching their path for different directions, develop streams in which they can move with the least possible collisions. This always happens although no one is planning this behavior.</p> <p>The spontaneous development of new system properties will happen while these properties could not be predicted upfront when inspecting the actors or components of the system. The so developed <em>new</em> is not more or less but something different than the sum of the parts. While the actors or components are visible, their interactions are invisible and difficult to measure. In particular, these interactions are the determining element in complex and self-organizing systems, they make the behavior of the system non-linear and difficult or impossible to reproduce – small causes can have enormous effects.</p> <p>We can find many examples in nature for strong self-organizational forces. The heart is a complex, self-organizing system. Single heart cells generate a synchronized electrical pulse excitation, leading to contractions in a steady rhythm.</p> <p>The neurons of the human brain can be described. Even their communication protocols can be analyzed. But who, by looking at these components of the system called a brain, could predict that from these neurons and synapses something like thoughts, feelings, music, dreams, and consciousness will develop? And isn´t it astonishing that the total number of neurons is determined with our birth – no further will be added — only the connections between the neurons and by that the possibility of interdependencies will increase during our lifetime.</p> <p>Language develops in the same manner. The interdependencies within our brains continue in the outer world. Thinking and speaking are connected and speaking – as only being one of many ways to communicate – connects our thinking with the thought of others. The language we use is not the result of a central construction process with the grammar specified upfront. Language evolves and can function without a primary constructing instance.</p> <p>The opponent of the described ordering forces is chaos. In the shape of turbulences and swirls chaos brings unpredictable dynamics and the moment of chance into the world. Complex self-organizing systems are situated along the border to chaos.</p> <p>In human organizations stabilizing rules and routines will be put against the chaos. But the so developed structures exist only as long as they are being reproduced and confirmed by the actors. Too many rules solidify the organization and prevent the adaption to new circumstances <a href="http://www.sbendel.ch/fileadmin/user_upload/PDF/IK_Vortrag_KFH.pdf">[Bendel 2006:2]</a>.</p> <p>Knowledge organizations are not able to survive without large degrees of freedom, because otherwise self-regulation, innovation, and adaption to changing environments cannot run fast enough and with the necessary quality.</p> <p>The reaction to unforeseeable events affords ad-hoc negotiation, the breakdown of routines and goal-oriented development of new rules to modify current structures.</p> <figure class="breakout"> <blockquote>Radically one has to leave behind the idea that everything in the organization can be ruled and controlled </blockquote> <figcaption>Sylvia Bendel</figcaption> </figure> <p>One has to withstand the reflex of responding to uncertainty and ambiguity with ever new rules, forms, and regulations. Instead one has to trust in self-organizational forces and the emancipation of employees to take local and autonomous decisions where needed.</p> <p>Still, not all decisions are being taken autonomously on local levels. Self-organization can be accompanied with hierarchic structures. Lower levels build up higher levels and higher levels adapt with a slower pace. Lower levels will get their orientation from higher levels and not the other way around. In self-organizing systems, impulse and input from lower levels will be integrated into decision processes. It is not the question if centralized or decentralized decision patterns are better in self-organizing systems. Instead, both patterns can be observed and are needed.</p> <p>This is a theory – but what can we <em>do</em> to give self-organizational forces a direction?</p> <h2 id="cooperation-and-communication">Cooperation and communication</h2> <p>For an organization to handle complexity properly, communication and cooperation processes need to be in good shape. If information can not easily find their way and flow to the right actors, a significant prerequisite for self-organization is violated which leads to a limitation of possible results. A culture of willingness to communicate and mutual understanding on all levels is essential. This will not happen without trust. Therefore, as an actor in a healthy functioning self-organizing system, say what you do and do what you say.</p> <h2 id="transparency">Transparency</h2> <p>Self-organization is about inspecting and adapt. Try to make the invisible visible and operate on facts. Determine the success criteria of your endeavor and ensure that everyone is operating on the same figures. If you need to make assumptions, make clear what assumptions have been taken and try to verify them as soon as possible. Be realistic and radical in terms of going to root causes, do not play down anything.</p> <h2 id="results-feedback-and-continuous-planning">Results, feedback, and continuous planning</h2> <p>If you know your strategic goal and you have your success criteria, inject sensors into your process. Regularly inspect your results concerning target achievement and to the actors behavior in the social context. These are two sides of the coin: adaption of behavior and target achievement are of equal importance. Only by maintaining these two dimensions, a social group can find its way for an upward movement and improve continuously. Based on the findings of the regular inspections you can plan for your next steps. Do not plan too far into the future, instead measure and inspect in short cycles if the planning leads to desired results and then adapt accordingly. You will find orientation and direction in the strategic goal that has been set before starting the endeavor.</p> <h2 id="performance-orientation">Performance orientation</h2> <p>If the organization has a goal and fulfills a purpose, results have to be delivered. One of the most critical tasks for the leaders of the organization is to define what outcomes need to be delivered what a good and what an unacceptable performance is [Malik 2009:293]. Self-organizational forces will get their direction out of this setting.</p> <p>In a social context often one has two options: routined good behavior or results-oriented new thinking. If the organization has to survive in a dynamic environment, routined good behavior is not an option anymore.</p> <p>The definition of great-, as well as unacceptable performance, does not mean to set internal stimulation by leveraging incentive systems. Daniel Pink [Pink 2009] points out that financial incentives will lead to worse and not to better performance when applied in complex environments. Incentives will improve exact the key figure where they are applied to, but everything else falls by the wayside.</p> <p>Wohland and Wiemeyer explain that internal stimulation with incentives creates mediocre results. They argue [Wohland and Wiemeyer 2007:62ff]:</p> <ul> <li>Incentives are an element of control. Like all control elements, they afford knowledge about the future. In a highly dynamic environment, the future is characterized by surprises. As incentive contracts cannot be adapted continuously, in dynamic environments, they point very likely in the wrong direction.</li> <li>Incentives treat all employees in the same way, without keeping individual talents, chances, and risks into account. The result is the average performance that anyone can achieve if he wants to, in other words, the average. That is less compared to what a talented person could achieve in her area of competence and not enough to compete with high performers.</li> <li>High performance presupposes a culture of trust. Top performers will stabilize such a culture by carefully ensuring that organizational and employee interests are compatible with each other. Incentives are a result of mistrustful thinking. In an incentive culture, the adding of value has to be achieved and stabilized through control and rewards.</li> <li>Motivation is a quality sign of good leadership. The need for internal stimulation through incentives is a hint that leadership still needs to be learned.</li> <li>Internal stimulation blocks or hinders the resistiveness of the led persons because incentives invite for uncritical pursuing of centrally defined goals. This increases the lack of leadership that initially produced the need for internal stimulation even more. The participation of the led people in the definition of goals does not change this conflict, because participation with this regards is often theater communication.</li> </ul> <h2 id="doing">Doing</h2> <p>Done work has momentum. Let your task permeate yourself until a solution arises. Act, deliver, inspect and improve. In the agile movement this attitude is captured by a collection of cute sayings: “Cut through the noise by taking action” [Beedle and Schwaber 2002:27], “Deliver early and decide late”, “Do, do right, do better”.</p> <p>This all comes down to, that in this complex self-organizing universe where always more is unknown than known theoretical models are not enough.</p> <p>Do the things that produce results now. Repeat.</p> <h2 id="divergent-convergent-thinking-and-responsibility">Divergent-convergent thinking and responsibility</h2> <p>Explore and expand possible solution spaces for a given problem. In other words, think divergent and do it in a team before deciding for a solution. Don´t settle easily for the first and obvious solution. Diversity is something valuable. Bear with different perspectives from different team members for a while and then start to converge.</p> <p>Possible techniques for divergent-convergent thinking are silent-brainstorming or the dynamics group decision making model by Sam Kaner [Kaner et al. 2007].</p> <p>I find it helpful to have a responsible person to speak the final word for strategic decisions at the end of such decision courses. In Scrum, for example, there is the Product Owner who speaks the last word for business-relevant decisions. The IT-Architect will talk the final word regarding architectural choices.</p> <h2 id="use-what-is-already-working">Use what is already working</h2> <p>Use what is working. Do not put everything all at once into question. Evolution will also not start from scratch every time.</p> <h2 id="the-networks-will-follow-their-task">The networks will follow their task</h2> <p>Our tasks determine our communication patterns. Make the task that has to be fulfilled absolute clear. This will lead to a task-oriented organization where teams will freely and on behalf of their duties form themselves and keep that order intact. A shared sense of belonging will not arise from social events, like Christmas dinners, but from shared goals and tasks <a href="http://www.sbendel.ch/fileadmin/user_upload/PDF/IK_Vortrag_KFH.pdf">[Bendel 2006:5]</a>.</p> <h2 id="anti-fragility">Anti-fragility</h2> <p>Nassim Nicholas Taleb coined the term anti-fragility [Taleb 2012]. Anti-fragility does not mean robustness. Robustness is the ability of a system to resist changes without modifying its initial stable structure. Anti-fragility is more. It is the ability to become stronger through drawbacks, impacts or enhanced demands. If you lift 50 kilograms on one day, your body starts preparing to lift 51 kilograms on the next day. You become stronger because you are getting trained. The same is true for self-organizing teams. As long as the task of the team is clear, the team will start to orient itself on the mission. The job is allowed to be demanding – but it has to be clear, and the team must be emancipated to change structures and adapt.</p> <h2 id="reflection">Reflection</h2> <p>I want to close with a suggestion for a reflection exercise from Jurgen Appelo. As a leader, write down two lists: One list with decisions that your team can make without you and one list with decisions you will make without involving your team [Appelo 2011:118].</p> <h2 id="references">References</h2> <dl> <dt>[Appelo 2011]</dt> <dd>Jurgen Appelo, “Management 3.0, Leading Agile Developers, Develop Agile Leaders”, Addison Wesley 2011</dd> <dt>[Beedle and Schwaber 2002]</dt> <dd>K. Schwaber, M. Beedle, “Agile Software Development with Scrum”, Pearson Prentice Hall, 2002</dd> <dt>[Bendel 2006]</dt> <dd>Sylvia Bendel, “Grenzen der Steuerung: Umgang mit Komplexität und Selbstorganisation”, Referat für die KFH-Tagung “Kommunikation von Fachhochschulen” Luzern 2006, <a href="http://www.sbendel.ch/fileadmin/user_upload/PDF/IK_Vortrag_KFH.pdf">http://www.sbendel.ch/fileadmin/user_upload/PDF/IK_Vortrag_KFH.pdf</a></dd> <dt>[Hayek 1969]</dt> <dd>Friedrich A. von Hayek, “Arten der Ordnung, Freiburger Studien, gesammelte Aufsätze”, Siebeck 1969</dd> <dt>[Hayek 2011]</dt> <dd>Friedrich A. von Hayek, “Law, Legislation and Liberty”, Volume 1: Rules and Order, University of Chicago Press, 2011</dd> <dt>[Kaner et al. 2007]</dt> <dd>Sam Kaner et al., “Facilitators Guide to Participatory Decision Making”, Jossey-Bass 2007, Second Edition</dd> <dt>[Malik 2009]</dt> <dd>Fredmund Malik, “Systemisches Management, Evolution, Selbstorganisation”, Haupt 2009</dd> <dt>[Pink 2009]</dt> <dd>Daniel Pink, TED Talk: “The puzzle of motivation”, TED 2009, <a href="http://www.ted.com/talks/lang/de/dan_pink_on_motivation.html">http://www.ted.com/talks/lang/de/dan_pink_on_motivation.html</a></dd> <dt>[Taleb 2012]</dt> <dd>Nassim Nicholas Taleb, “Anti-Fragility”, ZURICH.MINDS 2012, <a href="https://www.youtube.com/watch?v=zOUph1JpLlk">https://www.youtube.com/watch?v=zOUph1JpLlk</a></dd> <dt>[Wohland and Wiemeyer 2007]</dt> <dd>Gerhard Wohland und Matthias Wiemeyer, “Denkwerkzeuge der Höchstleister”, Murmann 2007</dd> </dl> Tue, 26 Mar 2013 00:00:00 +0000 https://ulf.codes/thoughts/self-organization/ https://ulf.codes/thoughts/self-organization/thoughts The agile worker <p>The agile worker exists because of discrepancies between theory and reality</p><p>An essential part of agile work is learning. Agile workers are knowledge workers who bring their mental models in contact with reality. The agile worker does exist because of discrepancies between theory and reality and because insights can be gained through these discrepancies. If the theory is not questioned by reality, if whether model nor reality play a role, then there is no learning. Then work does not require the quest for suitable solutions and work can be done by following instructions.</p> <h2 id="authority">Authority</h2> <p>The agile worker is searching for insights. If insights should have a meaning, they lead to decisions. This is a further characteristic of the agile worker: she makes decisions.</p> <p>The agile worker is acting best inside of a system where decisions will be taken at the level with most profound insights and not necessarily at the level with the most formal power.</p> <blockquote> Do not move information to authority. Move the authority to where the information lives. [Marquet 2012:49] </blockquote> <p>Such kind of authority is a central part of the leadership process in agile organizations. It also means the ability to take risks, to change the organization and to develop. This is not primarily to reduce the work of managers but to come to the best possible decisions [Appelo 2011:114].</p> <h2 id="self-organization">Self-organization</h2> <p>Now <a href="https://ulf.codes/self-organization">self-organization</a>, in dissociation to centralized control, comes into play. Jurgen Appelo very clearly shows that most things in this world come along without a central controlling instance [Appelo 2011:99]. The functioning of life is self-organized. The origin of species, of the world, went well without management and will go ahead even without management. With that background we have to realize that masterminded, centrally controlled large organizations are the exception and not the normal case. The thought is valuable, that self-organization of teams, which is of such importance in agile procedures, is the default behavior.</p> <h2 id="constraints">Constraints</h2> <p>In any complex system, in small companies and large corporations, self-organization takes place, and the constraints of the system give the direction for the self-organization.</p> <blockquote> <p>To give self-organizational forces a direction by setting constraints is the primary task for leaders of agile organizations</p> </blockquote> <h2 id="purpose">Purpose</h2> <p>Of course, all human-created organizations have a purpose, a goal. The decisions, the actions and the results that any organization delivers must be aligned with that purpose. Therefore self-organizational forces need have a direction.</p> <p>One example: In road traffic the established rules allow any road user to travel fast, save and to arrive at the desired destination. In the Netherlands roundabouts are a common way to organize traffic flow. In Germany, traffic lights are being used to achieve the same result. We all have made the experience to wait in front of a red traffic light at an empty crossing. In a roundabout nobody is waiting if there is no traffic. Decentralized self-organization of road users is required and has a direction because traffic rules are in place. On the other hand, traffic lights correspond to a central controlling model with high controlling costs, where self-organization is largely inhibited and occasionally delays.</p> <p>If a manager intervenes a current Sprint in a Scrum organization, the Scrum Team will start to behave like the driver at the red traffic light, which means waiting for signals – and not like a road user in a roundabout, which means autonomous searching a way.</p> <h2 id="what-and-how">What and how</h2> <p>It can not quickly be answered <em>how</em> to give self-organizational forces a direction. But one crucial aspect is to set the right constraints. Leaders should talk more “what” and less “how”.<br /> Identify the “what” that has a value and make it absolutely clear!</p> <blockquote> <p>Talk more “what” and less “how”</p> </blockquote> <h2 id="decisions">Decisions</h2> <p>The self-organizing team often makes decisions in a discourse. Possible solution spaces are being explored, and divergent opinions have to be endured because best solutions can arise by affirming heterogenous perspectives about a topic. The decision does not need to be taken democratically. We all deserve the same respect, but in a specific context, we are not all equal. Someone has more or less knowledge in the particular area of interest, is more or less experienced, can provide more or less orientation for the team to cope with the task. If real results have to be delivered and the team is committed to producing results, often a natural order of authority emerges which determines who has to or is allowed to speak the final word about a specific decision. A precondition for this is the collaboration-oriented and committed attitude of the team. This attitude requires the individual to share the consequences of a choice even if one has a different opinion. This requires to put the operating needs of the team above the individual preferences.</p> <p>To be against a decision is not the same as accepting and sharing a decision. In the first case, the team has to go through a clarifying conflict. Artificial harmony does not help to go further. Are all facts on the table? Assistance for team-oriented decisions can be found at the “Facilitator´s Guide to Participatory Decision-Making” by Sam Kaner [Kaner 2007].</p> <h2 id="roles-and-professions">Roles and professions</h2> <p>A finally responsible person can also take the weighed and reasoned decision. For example, the Product Owner in a Scrum Team has the right to speak the final word with regards to business-relevant decisions. The IT-Architect can do the same with regards to architectural decisions. A team leader of a technical component team can speak the final word in a discourse that does not come to an end. Of course here power is being exercised but I see it positive. Such behavior can be a service to the team. If final instances for decision making are embedded into the process and if these instances are willing and can take the responsibility, this will help all actors to move one step further. Roles and professions should not vanish in the team process. Instead, the ordering capabilities of different roles and professions have to be used for the better.</p> <p>It is essential how the decision is being derived, what is being learned during the discourse and how the decision can be reasoned. It is important to review if the choices lead to a functioning system. Upfront we can not always be sure if a decision brings an improvement or not. Therefore the agile worker prefers to work in an empiric process model. The essential characteristic of this process model is the continuous inspection and adaption, the short cycled comparison of mental model and reality.</p> <p>The defined process model, in which the apriori planning allows to predict which actions lead to specific outcomes, is not essential for the agile worker, because defined process models do not require learning and therefore no agile workers.</p> <p>Stop. This is too simple. Defined processes, when functioning, are mental models that are anchored in reality. Functioning defined processes are part of the agile worker’s toolbox. They are building blocks that can be combined to new solutions. They lower the amount of energy that is needed to come to results. Indeed they are to some extent part of the professional identity of the agile worker because this is what has been learned and what can be picked up to come to results faster, with lower risk and less energy input. The learning process is empiric; the learned is defined and will be reused to learn the new.</p> <p>Compare it to a child learning to tie the shoes. At first, this is an empiric process with all senses sharp. From the first success to the automatic procedure some time is required, and then no further thoughts go into it. Higher goals are to reach.</p> <p>Sometimes the most difficult task is in the questioning of the already learned. What was successful in the past may no longer help in the future. The agile worker should be prepared to move out of the comfort zone and to stand in for new insights. The new insight often does not have a lobby nor is it mainstream. Instead, the new insight will challenge the status quo. This will move boundaries, and it comes along with giving up personal safety. Because all new has to cleave its way.</p> <p>Like learning is in service to produce good decisions, good decisions are in service to produce good results. Agile workers deliver results. The more mature the agile worker is, the more the solving of problems is characterized by <em>accepting, internalizing, being permeated by the problem until a solution arises</em>.</p> <h2 id="many-of-us">Many of us</h2> <p>Is the idea of the self-determined, purpose-oriented and mastery-striving cooperative worker a model for many of us? I believe, yes. When we were children, we all started as agile workers. Then we have been socialized in schools, university, and corporate structures. If you want to have an idea about what happens during that way, have a look at the <a href="https://www.tomwujec.com/marshmallowchallenge">marshmallow challenge</a> – kindergarten children usually produce better results than business school graduates.</p> <p>Ideas change the world. Taylorism has done that and left us behind with apriori process planning and acting as resources in highly automated manufacturing processes. The changing world with new challenges and ever-increasing complexity will ask for our place in this world. Routined good behavior will no longer be the answer to that question. Creativity, exploring, understanding, changing, will become the usual case. The agile movement is a promising new idea and at the same time a reality-pattern that represents a more profound and groundbreaking change that is already on the way.</p> <h2 id="references">References</h2> <dl> <dt>[Appelo 2011]</dt> <dd>J. Appelo, “Management 3.0, Leading Agile Developers, Develop Agile Leaders”, Addison Wesley 2011</dd> <dt>[Kaner 2007]</dt> <dd>S. Kaner et al., “Facilitator´s Guide to Participatory Decision Making”, Second Edition, Jossey-Bass 2007</dd> <dt>[Marquet 2012]</dt> <dd>L. David Marquet, “Turn the ship around, A true story of turning followers into leaders”, Penguin 2012</dd> <dt>[Wujec 2010]</dt> <dd>T. Wujec, “The Marshmallow Challenge”, <a href="https://www.tomwujec.com/marshmallowchallenge">https://www.tomwujec.com/marshmallowchallenge</a></dd> </dl> Fri, 01 Feb 2013 00:00:00 +0000 https://ulf.codes/thoughts/the-agile-worker/ https://ulf.codes/thoughts/the-agile-worker/thoughts The art in our work <p>Challenging the status quo is art</p><p>This text was first published in OBJEKTspektrum, issue 5/2012, under the title <a href="https://ulf.codes/assets/schneider_os_05_12.pdf">“Die Kunst in der Arbeit, eine Herausforderung des Status quo”</a>. I have enhanced and translated the initial document to publish it here on <a href="https://ulf.codes">ulf.codes</a>.</p> <p>The Agile Manifesto <a href="http://agilemanifesto.org">[Beck et al. 2001]</a> represents a force that is behind any particular agile procedure like XP, Scrum or Kanban. This force, the culture to challenge the status quo, attracts certain people and companies.</p> <h2 id="people">People</h2> <p>Work is an integral part of human life. Otl Aicher writes basically: For humans, work is what for a spider is the net. As the net cannot exist without a spider and the spider cannot be without the net, likewise, work cannot exist without humans. We define our habitat by doing work. [Aicher 1992:28]</p> <p>We can understand our work as being oppressive, a craft or even art.</p> <p>Work that does not allow us to find a purpose, where we can not act self-determined or are exposed to monotonous stress, with little or no influence on the outcomes or where we can not identify ourselves with the results, oppresses us. We wear out in our doing and can not have an intrinsic motivation.</p> <p>In some IT-projects this way of working can be observed: More often than not there is no strong cost-benefit assessment with a conclusive strategic goal which is being understood by all members of the delivery team; for only some areas of responsibility there are many coordinators, coaches, consultants and managers, but for many programming tasks there are only some software developers; the produced code is of bad quality because of heavy time pressure and too few developers with the right skills; software that is being developed is not being used because the way it is build does not help the users doing their work; responsibilities are unclear, power is being exercised when it comes to track down the guilty parties but leadership is not being given; success is not being seeked because all energy is consumed to avoid only failure. This way of working does not safeguard our existence – instead, it causes disease. Here is a lot to lose and little to win. If you can not change the situation, try to leave.</p> <p>Projects are being deceived into such situations at first by managers. Managers are responsible for the way the systems works. If they miss setting the right constraints to foster and direct self-organizational forces, no guiding process can be established by the work-force level. The missing leadership creates a vacuum allowing disorder and lack of direction to flow in.</p> <p>If we see our work under the aspect of good workmanship, our thinking and acting will be guided by concepts of quality and work ethics. An electrician, for example, will not install a cable diagonally even if asked to do so by his customer. This is just against his work ethics.</p> <p>A software development team will establish a system of continuous integration or even delivery. If the environment is not prepared for that, the team will fight for it, because not to do so would hurt workmanship standards.</p> <p>The software craftsmanship movement <a href="http://manifesto.softwarecraftsmanship.org">[Bradbury et al. 2009]</a> can be seen under that impression – although this movement goes beyond workmanship, it is about art and craft.</p> <p>By claiming our work as being art, the development opportunities will expand for the individual, the team and the surrounding organization. Now it´s all about purpose, autonomy, and mastery. Seth Godin explains what art in work may be:</p> <figure class="breakout"> <blockquote> There used to be two teams in every workplace: management and labor. Now there’s a third team, the linchpins. These people invent, lead (regardless of title), connect others, make things happen, and create order out of chaos. They figure out what to do when there’s no rule book. They delight and challenge their customers and peers. They love their work, pour their best selves into it, and turn each day into a kind of art. </blockquote> <figcaption>Seth Godin</figcaption> </figure> <p>By Seth Godin’s definition an artist is</p> <figure class="breakout"> <blockquote>… someone who uses bravery, insight, creativity, and boldness to challenge the status quo. And an artist takes it personally. </blockquote> <figcaption>Seth Godin</figcaption> </figure> <p>Art is not decoration – it is a motor of change. And art will only be made by artists. In this sense, the heads behind the agile movement can be seen as artists.</p> <p>This interpretation of art in work is not only about individual expertise, but it is also about cooperation and social capabilities. Expertise and cooperation bring us to an up-movement, while in the opposite incompetence and egoistic driven acting bring us into a down-movement.</p> <p>In this regard, it is helpful that experienced people have an eye for other qualified people [Wohland and Wiemeyer 2007:40], so that they attract each other, which facilitates cooperation in the end.</p> <p>This confident and demanding expectation on us and our work is a force behind the Agile Manifesto and also the software craftsmanship movement. From that perspective, I think it is clear, that Agile is about individuals, their opinions, attitudes, creativity, skills and their willingness to cooperate.</p> <h2 id="organization">Organization</h2> <p>This perspective does not correspond with the model by that we have been socialized in the industrialized world during the last one hundred years. The schools, university, and working worlds functioned by a mainly different pattern: the Taylorism <a href="http://en.wikipedia.org/wiki/Frederick_Winslow_Taylor">[Wiki]</a>.</p> <p>The centralized planning, disassembly, and automation of work brought us to the integration of human work into precise production timing and to an understanding of companies as automatic production machines. Wohland and Wiemeyer explain the concept with their model of the Taylor-Tub.</p> <figure> <img src="https://ulf.codes/i/blog/taylor_tub.jpg" /> <figcaption>Figure: The Taylor-Tub [Wohland and Wiemeyer 2007:23]</figcaption> </figure> <p>In the Taylor-Tub the thoughts of the individual are not of importance, because all workflows, procedures, and processes are already defined upfront and have to be followed. This makes the system robust but inflexible. We have been educated for this world of working, which brought up disruptive productivity growth and inert mass markets during the last century. The biggest problem to solve for these markets: how to produce as much as possible at the lowest price.</p> <p>Narrowness and/or complexity characterizes Today’s markets. This complexity requires a better understanding of customer needs, higher flexibility and often interdisciplinary approaches. Those companies that can create such dynamics, the top performers, set the less capable companies under pressure. Companies that can not create the dynamics will suffer the pressure. The biggest problem to solve for these markets: how to connect to the customer, identify what delivers real value and be able to do it fast.</p> <p>The momentum is being created by dynamic people, by experienced and skilled workers who responsibly and self-organizing produce results. People who can bear with complexity. For those people, values and leadership are of much higher importance than centralized control and management.</p> <p>A template for congruent acting can be seen in the Agile Manifesto. And the similar attitude might be to understand our work as art.</p> <h2 id="perspective">Perspective</h2> <p>It is not about even more working. Instead, we need to care about a more suitable style of working nowadays, about personal progress and development. Those people and companies that understand their work as an art and who explore the field that will be opened through that thinking and acting, are the avant-garde of a new wave. Maybe this wave can be compared to the transformative power that Taylorism unfolded during the last century. The Agile Manifesto and also the software craftsmanship movement are patterns of this new reality. The related value systems can guide the path for the individual, the team and the company.</p> <h2 id="references">References</h2> <dl> <dt>[Aicher 1992]</dt> <dd>O. Aicher, “analog und digital”, Ernst &amp; Sohn, 1992</dd> <dt>[K. Beck et al.]</dt> <dd>“Agile Manifesto”, 2001, <a href="http://agilemanifesto.org">http://agilemanifesto.org</a></dd> <dt>[Bradbury et al. 2009]</dt> <dd>D. Bradbury et al., “Manifesto for Software Craftsmanship”, 2009, <a href="http://manifesto.softwarecraftsmanship.org">http://manifesto.softwarecraftsmanship.org</a></dd> <dt>[Godin 2010]</dt> <dd>S. Godin, “Linchpin, Are You Indespensable?”, Penguin Books, 2010</dd> <dt>[Schneider 2012]</dt> <dd>U. Schneider, “Die Kunst in der Arbeit, eine Herausforderung des Status quo”, OBJEKTspektrum, Ausgabe 5, 2012</dd> <dt>[Wiki]</dt> <dd>Wikipedia, “Frederick Winslow Taylor”, <a href="http://en.wikipedia.org/wiki/Frederick_Winslow_Taylor">http://en.wikipedia.org/wiki/Frederick_Winslow_Taylor</a></dd> <dt>[Wohland and Wiemeyer 2007]</dt> <dd>G. Wohland, M. Wiemeyer, “Denkwerkzeuge der Höchstleister, Wie dynamikrobuste Unternehmen Marktdruck erzeugen”, Murmann Verlag, 2007</dd> </dl> Fri, 31 Aug 2012 00:00:00 +0000 https://ulf.codes/thoughts/art-in-work/ https://ulf.codes/thoughts/art-in-work/thoughts Five dysfunctions of a team <p>A non-performing team is not a team</p><p>Deliver with each iteration a <a href="https://ulf.codes/definition-of-done">done</a> piece of work and collaborate as a team. If you do only these two things and forget about all the concepts and procedures we like to talk about in the agile world, you already have made a good part of the agile journey.</p> <p>Teams deliver — the better the team, the better the performance. We can not think about a team without thinking about performance. Some people being nice to each other and chatting around at the coffee corner does not mean they are a team. They may only be a group of people sharing the same coffee machine but not sharing their goals and rewards.</p> <p>Good teams find solutions. All, really all of our agile concepts and procedures do not work if they are not backed up by a functioning team.</p> <p>Patrick Lencioni provides with his “Five Dysfunctions of a Team” [Lencioni 2002:188] a model to understand how team dysfunctions will build on one another with worsening effects from layer to layer.</p> <figure> <img src="https://ulf.codes/i/blog/five_dysfunctions.jpg" /> <figcaption>Figure: The five dysfunctions of a team</figcaption> </figure> <div> <table> <tr> <th>Layer</th><th>Dysfunction</th><th>Behavioral pattern</th> </tr> <tr> <td>1</td><td>Absence of trust</td><td>Unwilling to be vulnerable within the group</td> </tr> <tr> <td>2</td><td>Fear of conflict</td><td>Seeking artificial harmony over a constructive passionate debate</td> </tr> <tr> <td>3</td><td>Lack of commitment</td><td>Feigning buy-in for group decisions creates ambiguity throughout the organization</td> </tr> <td>4</td><td>Avoidance of accountability</td><td>Ducking the responsibility to call peers on counterproductive behavior which sets low standards</td> <tr> <td>5</td><td>Inattention to results</td><td>Focusing on personal success, status, and ego before team success</td> </tr> </table> </div> <p>I find the model useful to analyze team dysfunctions, isolate root causes and work through each layer, starting with the most basic and going to the top. E.g., if you can not establish a trustful environment you will not be able to get real commitments.</p> <p>The dysfunctions can be rephrased to give a positive direction. To come to a lively and performing team, the team should</p> <div> <table> <tr> <th>Layer</th><th>Try to achieve</th> </tr> <tr> <td>1</td><td>Nurturing a trustful environment, allowing oneself to be vulnerable</td> </tr> <tr> <td>2</td><td>Have an open and fair communication culture and engage in conflict around ideas</td> </tr> <tr> <td>3</td><td>Commit to shared goals and decisions</td> </tr> <tr> <td>4</td><td>Hold each other accountable against the shared goals and decisions</td> </tr> <tr> <td>5</td><td>Focus on the achievement of collective results</td> </tr> </table> </div> <p>Lencioni offers a field guide for leaders, managers, and facilitators with exercises and concepts to overcome the five dysfunctions. [Lencioni 2005]</p> <h2 id="references">References</h2> <dl> <dt>[Lencioni 2002]</dt> <dd>Patrick Lencioni, “The Five Dysfunctions of a Team”, Jossey-Bass 2002</dd> <dt>[Lencioni 2005]</dt> <dd>Patrick Lencioni, “Overcoming the Five Dysfunctions of a Team: A Field Guide for Leaders, Managers, and Facilitators”, Jossey-Bass 2005</dd> </dl> Tue, 10 Jul 2012 00:00:00 +0000 https://ulf.codes/thoughts/five-dysfunctions/ https://ulf.codes/thoughts/five-dysfunctions/thoughts Definition of Done <p>A contract to begin your agile journey with</p><p>The <em>Definition of Done (DoD)</em> is not only a checklist that has to be executed to get a piece of work delivered. The DoD and the path to its determination opens a space for agile thinking and acting which can actively be leveraged by the delivery team and the surrounding organization. It is a great entry point for agile delivery, and it can be used in Scrum, Kanban or any other procedure with iterated delivery.</p> <p>To answer the simple question „When is a work item done?“ will produce insights into the flow of work. At first, this question should be discussed and negotiated by the team who wants to get the job done. The perspective is general for all items that are to be delivered – usually, the team has only one DoD that will be used for all of those work items. That means the team will think about the general good flow of the majority of work items and not about every exception that may occur or every specific work item that needs some other work steps.</p> <p>For a start, the chain of work steps is of interest. Collect the steps for example on sticky notes and put them on a wall or a whiteboard. This will show unnecessary, missing or insufficient steps. Do it among the members of the delivery team – when leveraging Scrum with the entire Scrum Team, including Scrum Product Owner. It does not take a lot of time, and it is an excellent exercise to bring the people together. The produced result is something that the members of the team can identify with, and that can later be referred to.</p> <p>E.g., a short list of possible steps that are needed to get a piece of software done might be:</p> <div> <table> <tr> <th>Work steps</th> </tr> <tr> <td>The requirement in User Story syntax</td> </tr> <tr> <td>Discussion about solution</td> </tr> <tr> <td>Testcases developed</td> </tr> <tr> <td>Implemented with unit tests</td> </tr> <tr> <td>Acceptance criteria met</td> </tr> <tr> <td>Performance fulfilled</td> </tr> <tr> <td>Translations</td> </tr> <tr> <td>Documentation</td> </tr> <tr> <td>Enduser tests</td> </tr> </table> </div> <p>The team has to discuss, negotiate and conclude on the proper work steps. As a result, the team earns a clear understanding of “done” software in a specific context. This is an important contract to ensure not to break the product during iterated delivery and to have defined quality for any “done” piece of software in each iteration.</p> <blockquote> <p>Write down your current <em>Definition of Done</em> and provide it somewhere so that anyone can immediately access it. Make it explicit. Stick to it.</p> </blockquote> <p>The team can modify the contract of the <em>Definition of Done</em> after each iteration. These discussions have a significant impact on making the flow of work visible, on seeing if the team can do the work and to unhide bottlenecks. But be aware not to make the DoD so thin that at the end a piece of work that fulfills your DoD is not done. Remember, almost done is easy, but that is not done.</p> <p>This will show very soon if the right people with the right skills to deliver are in the team and what the interfaces and dependencies to the teams outside world are.</p> <p>If the team cannot perform some work steps, it needs to be decided if the team has to reshape with different team members or if interface contracts with <em>external</em> providers are to be concluded on. The definition of interfaces will anchor the team inside the surrounding organization. This not only makes clear the external dependencies of the team but also gives a lever to change the organization. Many external interfaces provide a hint that the team structure is not optimal to get the work done.</p> <p>The delivery team as a whole is responsible for performing the work steps and for delivering “done” work. Albeit, usually for some tasks specialized skills are needed, and only some of the team members can perform these tasks. This is backed up with some good reasons. E.g., the appropriation of the relevant knowledge takes a lot of time and energy – sometimes a work life – or because the task is so complex that the interdisciplinary collaboration of different team members is required. To understand team responsibility in terms of <em>everyone in the team can do everything</em> is an error in reasoning. Instead, the team should focus on fearless communication and leverage different talents. Use the differences and find ways to come together. Heterogenous tasks demand heterogenous teams. Keep up the professions because the work ethics that typically come along with a profession will enhance the teams’ capabilities.</p> <p>I do not speak for total specialization with only one specialist for each work step. Where ever possible, work should be performed by the next team member who can do it. Everyone should be prepared to help out each other. But to demand everyone in the team being able to do the same things, in my impression would mean that the team can do only average work. Talents in their specific area of competency can perform better and achieve more.</p> <p>Sometimes it is of help to write down some professional roles that are needed to fulfill the tasks. The list with the work steps could be extended by writing proper skill sets or roles beside the work steps.</p> <div> <table> <tr> <th>Work steps</th><th>Role</th> </tr> <tr> <td>The requirement in User Story syntax</td><td>Domain expert</td> </tr> <tr> <td>Discussion about solution</td><td>Domain expert and team</td> </tr> <tr> <td>Testcases developed</td><td>Test expert and domain expert</td> </tr> <tr> <td>Implemented with unit tests</td><td>Developer</td> </tr> <tr> <td>Acceptance criteria met</td><td>Developer and domain expert</td> </tr> <tr> <td>Performance fulfilled</td><td>Developer and domain expert</td> </tr> <tr> <td>Translations</td><td>Translator and domain expert</td> </tr> <tr> <td>Documentation</td><td>Technical writer and domain expert</td> </tr> <tr> <td>Enduser tests</td><td>User</td> </tr> </table> </div> <p>If members of the team cannot fill some roles – because of a lack of skills or because no member will take over the responsibility coming along with the role – you may have found an organizational dysfunction. Identifying the root cause is worth it. Why is the role so difficult to fill? What can be changed?</p> <p>The <em>Definition of Done</em> is a list that is of help for the Scrum Product Owner to validate work results at the end of a Sprint and to decide if work will be accepted or rejected. At the same time, the Scrum Development Team is aware from the start what needs to be done to get a piece of work approved by the Product Owner. For strategic estimation of Scrum User Stories with Story Points it is also crucial for the Development Team to know what work steps are to perform in general.</p> <p>Start where you are now. The <em>Definition of Done</em> can be the first step of your agile journey. Stick to your DoD and deliver.</p> Tue, 03 Jul 2012 00:00:00 +0000 https://ulf.codes/thoughts/definition-of-done/ https://ulf.codes/thoughts/definition-of-done/thoughts Scrum and Architecture <p>The architect and his tools in the Scrum process</p><p>This text was first published in OBJEKTspektrum, issue 4/2011, under the title <a href="https://ulf.codes/assets/schneider_os_04_11.pdf">“Scrum und Architektur, konzeptionelle Integrität im Scrum Prozess”</a>. I have reworked, enhanced and translated the initial document to publish it here on <a href="https://ulf.codes">ulf.codes</a>.</p> <p>Cooperatively making architectural decisions, at a point in time when they are needed – and not earlier – is a quality-improving paradigm in agile software development. Conceptual integrity in the flow of architecture decisions will only be achieved if one person has the final word regarding those decisions. This is the architect, serving the product, whose rights and obligations in the context of the Scrum process are being reflected in this essay.</p> <h2 id="iterations">Iterations</h2> <p>Scrum is team-oriented and separates the delivery process into subsequent iterations, so-called Sprints. The question arises how a conceptual integer architecture, an architecture that is intuitively understandable for users, developers and operators, easy to use even after many iterations, can be achieved while the team is focusing on the microcosm and solution patterns of current iterations.</p> <p>To achieve conceptual integrity, it has to be considered during the entire design and delivery process of a software solution. In this essay, you will find organizational and manual suggestions with the purpose to support conceptual integrity in the Scrum process. I will emphasize the role of the architect as an essential player with heavy responsibilities for the conceptual integrity of the software product.</p> <h2 id="scrum-and-architecture">Scrum and Architecture</h2> <p>The <a href="http://agilemanifesto.org">Agile Manifesto</a> values <em>“responding to change over following a plan”.</em> By taking this statement seriously, we accept that it makes sense to inspect our behavior and our achievements in a continuous manner. We do this to learn, to adapt and to come to better and more appropriate solutions while delivering results.</p> <p>Scrum is a team-oriented management framework for agile product development that creates transparency and has this kind inspect and adapt built in. Work is being <em>“done”</em> every two or so weeks, and at the end of these so-called Sprints, a process inspection and a product inspection is being held by the delivery team.</p> <p>Software development is a learning process. After finishing a project, we usually know more than we did when we started the endeavor. This requires to make architectural decisions as late as possible to leverage the knowledge that has been obtained while delivering results because decision quality can be enhanced by following this approach. In addition to late decisions, we deliver working software as early as possible, to learn by doing, to avoid endless discussions and to use the momentum of done work. Ken Schwaber and Mike Beedle coined the statement <em>“cut through the noise by taking action”</em> [Beedle and Schwaber 2002].</p> <p>By putting these two behaviors together, we have an approach that can be called <em>“deliver early and decide late”</em>.</p> <blockquote> <p>Deliver early and decide late</p> </blockquote> <p>Architectural decisions are strategic for the solution space. They affect many aspects of the solution and will be recognized by the users of the product. Architectural decisions define the solution space for a given problem and bridge the gap between the requirements and the implementation. It is the architecture that allows adapting a software system with a reasonable effort for changing requirements.</p> <p>Architectural decisions are being taken under two premises [Friedrichsen 2010]:</p> <blockquote> Represent and balance the interests of all stakeholders over the entire system lifecycle and<br /> Minimize the total cost of ownership for the system during the whole lifecycle </blockquote> <p>Here the balancing aspect of the interests of all stakeholders is emphasized. The famous Frederick Brooks [Brooks 1995:45] states, that</p> <blockquote> The architect of a system, like the architect of a building, is the user´s agent </blockquote> <p>My impression is, both quotes are correct.</p> <p>To me, design decisions, compared to architectural decisions, are of tactical or operational nature for the solution space. Design decisions make a structure inside of the solutions space, and the architectural choices span the solution space itself. The transition between architecture and design might be flowing.</p> <figure> <img src="https://ulf.codes/i/blog/architecture_bridge.jpg" /> <figcaption>Figure: Architecture as a bridge between the problem- and the solution space. Arrows are indicating mutual influence.</figcaption> </figure> <p>The cooperative role model of Scrum does not explicitly mention the architects’ role. Except for the Product Owner, the Scrum Master and the Development Team no other roles are named. It is supposed that the members of the Scrum Team will self-organize and find suitable solutions.</p> <p>But in that model, how will architectural decisions be taken? Are they a result of a team-oriented brainstorming and is the decision <em>„emergent“</em>, as long as the decision is being taken <em>„late“</em>? How is it ensured that the decisions follow a consistent concept and lead to conceptual integrity? My thesis is that the cooperative derivation of architectural decisions improves decision quality, but that conceptual integrity can only be achieved for the system if the final decision-making competency is in the hand of one or at a maximum two closely collaborating persons.</p> <h2 id="human-and-process">Human and process</h2> <p>Good architecture has conceptual integrity. One question is, can this be achieved by organizational measures, like processes and organizational structures, or is the expertise of an experienced and inspired architect of higher importance?</p> <p>From the perspective of agile software development, the answer is easy to find. The first value statement of the Agile Manifesto states that <em>“individuals and interactions are valued higher than processes and tools”</em> <a href="http://agilemanifesto.org">[Agile Manifesto]</a>. Therefore in an agile environment, the architect always has a higher significance than any architecture process.</p> <p>And there is even another reason to favor the person over the process. Software development requires social and communicating skills as well as engineering excellence and creativity. For an innovative product, creativity is a vital solution ingredient. Humans are creative, not so processes. , but any organization will only help if creative people in general and creative architects, in particular, are highly valued in the context of software development.</p> <p>This does not mean that the organization can be overlooked when we design the fields of work. The organization is in service to make the communicative and social aspects of software development efficient. The structures we chose will be reflected by the product we create. <em>“Conway´s Law”</em> <a href="http://www.melconway.com/Home/Conways_Law.html">[Conway 1968]</a> gives us the essential point of view:</p> <blockquote> <p>Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization´s communication structure.</p> </blockquote> <p>Rephrased: Our communication structures will be found again in the product.</p> <p>A complex organization with many employees and unclear responsibilities will lead to a bloated product. A lean organization with competent employees and clear responsibilities will produce a sharp and focused product.</p> <p>Scrum with it´s underlying reduction-minded, team-oriented and result-oriented setup is an excellent tool to create sharp and focused products. The architect in Scrum is the helping hand to keep the conceptual integrity in the product.</p> <h2 id="multi-team-setup">Multi-team setup</h2> <p>In multi-team projects, it is likely that your teams are traditionally formed around architectural components. You may have a frontend and a backend team or a mobile and a web team with team leaders and the like.</p> <p>This grouping of teams by components helps to bundle component know-how and to keep the components intact, but it usually does not contribute to delivering end-to-end features fast and without friction, because the teams are waiting for each other and blocking themselves. Communication is more difficult, takes more time and if the component teams are placed in different locations the hurdles are even higher.</p> <p>With the only perspective of component teams, the project can quickly get into the fallacy of delivering only parts without end-to-end integration in each Sprint. A feature that can be inspected by a customer or a Product Owner will then only be visible after some Sprints.</p> <p>Therefore I suggest the following approach: stay with the component teams – they help to bundle component know-how. But for the delivery of features also have <em>virtual</em> feature teams that consist of people from several component teams – merely those people who anyway need to come together to let the end-to-end feature become a reality. For these feature teams often a Daily Scrum makes much more sense than for a component team because they are hunting for a feature and use the Daily Scrum to ensure the end-to-end readiness and delivery of the function.</p> <p>In such an organization component teams, virtual teams and the architect will discuss from time to time difficult changes (for example API changes) that belong to components. These changes may be required and indicated by a <em>virtual</em> feature team. And it may be the same person who suggests the need for a change from inside of the feature team, bringing it to his <em>home</em> component team, participating in the discussion and coming back with a solution approach to the feature team.</p> <p>The <em>virtual</em> feature teams may change from time to time – whenever the next feature to be delivered requires a different team setup.</p> <p>This multi-team organization, which forms a matrix with the axes <em>feature</em> and <em>component</em> will support both dimensions: the component architecture and fast, communication-oriented end-to-end feature delivery.</p> <p>In the text below, when examining some tools for the architect, please refer to the End-to-End-Skeleton. This is a technique that supports feature delivery even in multi-team setups.</p> <h2 id="the-architect-in-scrum">The architect in Scrum</h2> <p>Coming from the organization to the individual, we have to think about the architects’ role. Here are some suggestions to embed the architect into a Scrum endeavor:</p> <ul> <li><strong>Embedded:</strong> If the architect is part of the Scrum Development Team or if a more separate position is needed, depends on the size of the project. If the entire project is made up of a single Scrum team, the architect will merely take his role inside of the Development Team. In case more than one Scrum Team is needed, the architect will have a more exposed position which is comparable to the exposure of the Product Owner.</li> <li><strong>Decision competency:</strong> Analogous to the decision competency of the Product Owner regarding business decisions, the architect has the final word regarding architecture decisions. He helps to define the product.</li> <li><strong>Member of the project:</strong> The architect is proactively responsible for the architecture of the solution space. And she is expected to have the same willingness to collaborate and drive to improve the development process as it is expected from all other team members.</li> <li><strong>Coding skills:</strong> The Scrum Team accepts the architect. Her contributions enrich the product, and she provides benefits to the team. For software development projects it is inevitable that the architect can write code to understand technical details and working dynamics. In most cases, the background of an architect is technical. This requires her to be open and to be willing to learn the essential aspects of the business or problem domain.</li> </ul> <p>This is a lot to expect from an architect. But the same is true for all other members of a Scrum Team. A developer is supposed to be on top of his craft, and a Product Owner must be able to influence his organization and have high competence in making business-relevant decisions to serve the product. The business experts need to be able to develop concise requirements and even test cases. Vice versa the architect must be able to fill out his role or at least has to learn the relevant aspects throughout the project.</p> <h2 id="architecture-by-committee">Architecture by committee</h2> <p>Don´t do it. Companywide architecture committees that are being fed with decisions from under-ordinated projects and that guard, release or reject architectural decisions are a bottleneck for the enterprise and the involved projects. The parties are blocking themselves on the search for synergy. Responsibility is being carved out of the projects into the superordinated committee where focus, involvement, competence, and understanding are not bound to the projects that need the decisions.</p> <figure> <img src="https://ulf.codes/i/blog/architecture_committee.jpg" /> <figcaption>Figure: Architecture by committee is the guarantee for a bloated product</figcaption> </figure> <p>Because of too many players with different interests the decisions being taken are often not focused enough and for none of the involved projects optimal.</p> <blockquote> <p>Architecture by committee is the guarantee for a bloated product.</p> </blockquote> <p>A companywide architecture committee should instead define constraints and architectural goals for the enterprise architecture and refrain from intervening the project work – except the project architect asks for it. To achieve results for real-world situations, it is helpful to have the same architects that work in delivery projects inside of the architecture committee. But it is essential to distinct committee goals and project work.</p> <p>Project architects, on the other hand, have to follow the architecture constraints and goals given by the committee. Within this given space the architect derives architectural decisions on behalf of the project and in cooperation with the team. The architect is responsible for his choices – this includes the decision about how and when to involve the architecture committee.</p> <p>Avoid architecture by committee [Brooks 2010:39]. The architecture is in the hand of the architect and not in the many hands of the committee. Architecture by committee is the guarantee for a bloated product.</p> <h2 id="tools">Tools</h2> <p>In the following, I will propose some concrete tools that help the architect and the team to drive the architecture. These tools are mainly known in the IT architecture domain, and I will only make suggestions on how to use them inside of the Scrum process.</p> <h2 id="start-with-the-vision">Start with the vision</h2> <p>The Product Vision contains and communicates the strategic goals of the endeavor. The vision will give self-organizational forces a direction. Whenever during the project course a decision needs to be taken, it must not contradict the goals of the vision.</p> <p>One approach for developing such a vision is Geoffrey Moore´s elevator pitch. The basic idea behind is that you should be able to explain the greatness of your product idea during an elevator ride. You can use the following template to prepare the elevator pitch:</p> <blockquote> For [customer, user]<br /> with [needs]<br /> is [productname]<br /> a [productcategory]<br /> that has [attributes, values, a reason to buy].<br /> Other than [competitor alternatives]<br /> is [productname] a [differentiation of the product]. </blockquote> <p>To go even one step further and anchor the vision within your business model, the <a href="http://www.businessmodelgeneration.com">Business Model Canvas</a> by Alexander Osterwalder and Yves Pigneur may be of use.</p> <blockquote> <p>It is one of the Product Owners obligations to prepare a convincing Product Vision.</p> </blockquote> <p>The architect has an interest in the Product Vision, too. Often architectural goals are bound to the product vision. These often non-functional goals may be explicit or implicit, but they are by definition of strategic nature. To identify and make them explicit is in the responsibility of the architect.</p> <p>In addition to the business goals that are given by the Product Owner, the architect has to identify the relevant stakeholders and find the architectural goals by deriving them from the business goals. But keep in mind, the architect does not invent the architectural goals – she only makes them visible by deriving them from the business goals.</p> <h2 id="architecture-vision">Architecture Vision</h2> <p>The architect will work closely together with the Product Owner to align the goals. Once identified, the architecture goals will be listed in an Architecture Vision statement or be embedded in the Product Vision.</p> <p>As an architect you should not jump into a project if this work can not be done, otherwise, chances for project success are limited from the start. It is like the saying: <em>“A shirt will never fit right if you miss the first buttonhole.”</em></p> <p>How important the knowledge of architectural goals are, can be seen in the following figures, that stand for different architectural goals:</p> <figure> <img src="https://ulf.codes/i/blog/architecture_goals.jpg" /> <figcaption>Figure: The importance of architecture goals</figcaption> </figure> <p>Sometimes an Architecture Overview Diagram is part of the Architecture Vision. The <a href="https://ulf.codes/bbl">Box-Bullet-Line</a> notation can be of help to draw the diagram and visualize process flows between architecture components.</p> <h2 id="system-context-diagram">System Context Diagram</h2> <p>The System Context Diagram explains the environment of the system. The system itself will be seen as a black box. The important part is to understand the surrounding forces that affect the system with their input- and output-interfaces, system boundaries and responsibilities. Such forces are users as well as resources and other systems.</p> <figure> <img src="https://ulf.codes/i/blog/system_context.jpg" /> <figcaption>Figure: System Context Diagram. Understand the environmental forces that are affecting the system.</figcaption> </figure> <p>The system itself will be drawn as a circle in the middle of the diagram. All surrounding components, systems, and resources acting upon the system will be illustrated as boxes and users will be drawn as stick figures. Communication and data streams will be depicted as arrows between the system and the environmental forces.</p> <p>Non-functional requirements, like the number of data records that have to be transmitted in a specific amount of time over a communication line or the number of users hitting the system at peak times, can be placed as weights beside the arrows or at the surrounding component boxes.</p> <p>The System Context Diagram is of value in early project stages and throughout the entire project. It is best developed in a group effort together with the stakeholders of the system. By group-working, the different perspectives on the system can be visualized quickly, and the architect has a hook to communicate with the stakeholders. Just draw the system in the middle (use a Metaplan board or a whiteboard). The surrounding elements can be placed by using sticky notes or moderation cards. When leveraging this technique, you can quickly move the environmental factors around and develop your System Context.</p> <h2 id="constraints">Constraints</h2> <p>Technical or organizational limitations are to be considered in any project. Constraints limit the solution space that can be spanned by the architect. At the same time, constraints provide anchoring points for the solution architecture.</p> <p>Constraints may be given by the presetting to use an enterprise-wide directory service, or by a time frame that is available for batch processing of data entries, or by queueing interfaces to existing systems. A given cost limit is a constraint, too.</p> <p>To maintain the list of constraints that are of relevance for the project is a task for the architect.</p> <p>Constraints are among the many factors that lead to non-functional requirements.</p> <h2 id="non-functional-requirements">Non-functional requirements</h2> <p>Non-functional requirements often are system-wide and can therefore not be attached to a single User Story.</p> <p>The strategic non-functional requirements lead to the architecture goals that will be documented in the Product Vision or the Architecture Vision.</p> <p>But there are also non-functional requirements that will influence the system architecture and do not find their way into the vision statements. A good entry point to identify any non-functional requirements is the System Context Diagram. It helps to determine requirements regarding reliability, performance, scalability, security, and maintainability.</p> <p>Because of the system-spanning nature of non-functional requirements, the architect must identify, document and communicate these requirements.</p> <p>The list of relevant non-functional requirements has to be maintained by the architect. This list can be a part of the Architecture Vision or be a separate document.</p> <p>Only in case, a non-functional requirement can be directly attached to a specific User Story, it should be documented besides the Story (e.g. in the acceptance criteria). In other cases, a separate document that collects all non-functional requirements serves the purpose better to understand the system stressors.</p> <blockquote> <p>The architect has to transform the non-functional requirements into measurable quantities that allow the easy observance of compliance or violation. This gives all actors a direction and makes it easier to fulfill the requirement during development.</p> </blockquote> <p>In particular, the following technique of the constraining resource needs this kind of measurable quantities.</p> <h2 id="constraining-resource">Constraining resource</h2> <p>When crafting a system, the non-functional requirements, constraints and architecture goals will lead the project team to the limiting or restraining resources.</p> <figure> <img src="https://ulf.codes/i/blog/constraining_resource.jpg" /> <figcaption>Figure: The constraining resource gives the key limit that determines the performance of the system</figcaption> </figure> <p>These resources give the fundamental limits that determine the performance of the system. The architect has to identify the scarce resources and derive allowable targets that can be used to measure and compare.</p> <p>As an example: 2,500,000 data records need to be processed within one hour. Currently achieved value is 1,800,000.</p> <blockquote> <p>To identify the critical limit, make it visible and establish an environment to measure continuously the current ability of the system to achieve the target, is a significant task for the architect.</p> </blockquote> <p>The achievement of the target should be checked and communicated daily. This information will give direction for the delivery team and will foster self-organization towards the completion of the objective.</p> <h2 id="box-bullet-line-bbl">Box-Bullet-Line (BBL)</h2> <p>The Box-Bullet-Line diagram is a pragmatic way to visualize flows between components. It can be used to model the Architecture Overview (see above, Product Vision or Architecture Vision) or to model some details of the system.</p> <blockquote> <p>The strength of the notation is, that it is intuitively understandable by the members of the project team so that the diagram can foster communication and is supporting a shared understanding of the inner system structure and behavior.</p> </blockquote> <p>Unlike the System Context diagram, which gives a black box perspective on the system, the BBL is a white box view. We want to understand what parts are essential and how the data and control flows between these parts.</p> <p>Please refer to <a href="https://ulf.codes/bbl">Box-Bullet-Line</a> to get more details.</p> <p>The BBL diagram can be used as a starting point for Storyboards and End-To-End-Skeletons.</p> <h2 id="storyboard">Storyboard</h2> <p>In Scrum, we handle with requirements in the form of User Stories. The Product Backlog is an ordered list of User Stories.</p> <p>A User Story does not explain how to build it. That is intentional. The User Story says what, why and gives context, but it does not tell the how to give room for self-organization.</p> <blockquote> <p>The Storyboard supports the mapping from the <em>“what”</em> to the <em>“how”.</em> The relevant tasks for a specific Story will be visualized in the context of the components they belong to.</p> </blockquote> <p>You start with a BBL diagram that contains the components you think are needed to build the Story. Draw the BBL on a flipchart or whiteboard. Now you break down the story into tasks by writing down each task on a sticky note and placing it on the component it belongs to in the BBL diagram.</p> <figure> <img src="https://ulf.codes/i/blog/storyboard.jpg" /> <figcaption>Figure: Storyboard. The relevant tasks for a specific User Story will be visualized in the context of the components they belong to.</figcaption> </figure> <p>This visualization helps all involved team members to identify the connection of the tasks. The mapping from User Story to tasks supports the goal of any architecture as an intermediary between business requirements and the concrete solution structure. The Storyboard improves the understanding of the solution structure for your User Stories.</p> <h2 id="end-to-end-skeleton">End-To-End-Skeleton</h2> <p>In multi-team setups, an integrated feature delivery can be achieved by using the End-to-End-Skeleton technique [Brooks 1995:267]. By following this approach all components that are needed for a specific feature will be involved right from the start of development.</p> <p>Essential is an initial interface definition between the components. Even this definition may change later, but you have to use a technical contract right from the start to model the end-to-end flow and make the programming efforts operational.</p> <p>For sure it will occur that some functionalities will be developed later and some earlier. The later ones need to be represented by test doubles (like a stunt double in movies, but in software development, these doubles are mocks, fakes or stubs) <a href="http://www.martinfowler.com/articles/mocksArentStubs.html">[Fowler 2007]</a>. The test doubles can produce some results for specific datasets but are no productive implementation of the needed functionality. Test doubles allow testing early some end-to-end flows.</p> <p>The purpose of the End-to-End-Skeleton is a full-length flow through all components that are touched by the new feature. This ensures from the start an integrated view of all actors and the development is being bound to concrete interfaces. It becomes immediately visible if the full-length flow is interrupted at any point.</p> <p>The technical specification of the interfaces should be in the hand of the architect or at least he should be part of the discussions that lead to interfaces, so that an over-arching understanding can be kept up and the data flow, as well as the interfaces, can be brought into the most straightforward possible format without duplicate or missing structures and attributes.</p> <h2 id="architecture-decisions">Architecture decisions</h2> <p>Architecture decisions represent the deliberate spanning of the solution space. Architecture decisions are anchoring points for further choices. Being such anchoring points makes architecture decisions challenging to change later on. With Stefan Zörner [Zörner, 2010] we can say</p> <blockquote> <p>The one who is in charge of deriving architecture decisions in an understandable manner develops the architecture.</p> </blockquote> <p>All aspects and tools that we have touched so far influence how architecture decisions are being taken.</p> <p>Architecture decisions need to be communicated. Besides the spoken language, which is a central part, the written form cannot be omitted. By writing down architecture decisions, the entire team or project will be enabled to trace even long in the past taken decisions. Stefan Zörner [Zörner 2009] has a real practical approach for the derivation and documentation of architecture decisions, which goes merely by writing down the answers to the following questions:</p> <ul> <li>Problem <ul> <li>What in detail is the problem?</li> <li>Why is it of relevance for the architecture?</li> <li>Which impacts does the decision have?</li> </ul> </li> <li>Constraints <ul> <li>What constraints need to be considered?</li> <li>What influencing factors need to be considered?</li> </ul> </li> <li>Assumptions <ul> <li>What assumptions have been made?</li> <li>What assumptions can be validated?</li> <li>What risks exist?</li> </ul> </li> <li>Alternatives <ul> <li>What alternatives have been examined?</li> <li>How is each of the other options being assessed?</li> <li>What alternatives are by intent being skipped?</li> </ul> </li> <li>Decision <ul> <li>What is the decision?</li> <li>Who took the decision?</li> <li>How is the decision being reasoned?</li> <li>When was the decision made?</li> </ul> </li> </ul> <p>I always find it helpful to go through these questions. It helps to clear the mind.</p> <h2 id="conclusion">Conclusion</h2> <p>The here made suggestions are explicitly not meant to make the Scrum framework more complicated or to inject an additional hierarchical level just for the architect. Also, traditional architecture tools, of which only some are being mentioned here, should not be replaced by the here mentioned. Instead, these elaborations should describe what the architects’ role is about in the context of the Scrum role model and what concepts and tools are of use in that case.</p> <p>The essay is a plea for the rights and obligations of the architect acting inside of the Scrum process; towards collaboration in the Scrum Team and against architecture by committee. I hope you can use some of the here made suggestions in your current or your next endeavor.</p> <h2 id="references">References</h2> <dl> <dt>[K. Beck et al.]</dt> <dd>Agile Manifesto, 2001, <a href="http://agilemanifesto.org">http://agilemanifesto.org</a></dd> <dt>[Beedle and Schwaber 2002]</dt> <dd>K. Schwaber, M. Beedle, “Agile Software Development with Scrum”, Pearson Prentice Hall, 2002</dd> <dt>[Brooks 1995]</dt> <dd>F. P. Brooks, “The Mythical Man Month”, Addison Wesley 1995</dd> <dt>[Brooks 2010]</dt> <dd>F. P. Brooks, “The Design of Design”, Addison Wesley 2010</dd> <dt>[Conway 1968]</dt> <dd>M. E. Conway, “How Do Committees Invent?”, 1968, <a href="http://www.melconway.com/Home/Conways_Law.html">http://www.melconway.com/Home/Conways_Law.html</a></dd> <dt>[Fowler 2007]</dt> <dd>M. Fowler, “Mocks Aren´t Stubs”, 2007, <a href="http://www.martinfowler.com/articles/mocksArentStubs.html">http://www.martinfowler.com/articles/mocksArentStubs.html</a></dd> <dt>[Friedrichsen 2010]</dt> <dd>U. Friedrichsen, “Wer braucht einen Architekten? Über Ziele und Aufgaben von Architektur und Architekten”, OBJEKTspektrum, Ausgabe 3, 2010</dd> <dt>[Osterwalder]</dt> <dd>Business Model Canvas, <a href="http://businessmodelgeneration.com/book?_ga=1.264929356.2127012834.1431598082">http://businessmodelgeneration.com/book?_ga=1.264929356.2127012834.1431598082</a></dd> <dt>[Schneider 2011]</dt> <dd><a href="https://ulf.codes/assets/schneider_os_04_11.pdf">U. Schneider, “Scrum und Architektur, konzeptionelle Integrität im Scrum Prozess”, OBJEKTspektrum, Ausgabe 4, 2011</a></dd> <dt>[Zörner 2009]</dt> <dd>S. Zörner, “Historisch gewachsen? – Entscheidungen festhalten”, Java Magazin 04/2009</dd> <dt>[Zörner 2010]</dt> <dd>S. Zörner, “Gretchenfrage 2.0: Was unterscheidet Softwarearchitekten von Entwicklern?”, Java Magazin 10/2010</dd> </dl> Mon, 27 Jun 2011 00:00:00 +0000 https://ulf.codes/thoughts/scrum-and-architecture/ https://ulf.codes/thoughts/scrum-and-architecture/thoughts The Box-Bullet-Line (BBL) <p>An intuitive and natural notation to communicate flows between components</p><p>Many important aspects of software development are invisible. When creating software we work through different abstraction layers by analyzing symbols and writing code.</p> <p>Writing software is comparable to the work of an author writing a book. Of course, there are engineering elements and creative and social aspects that characterize the work of a software developer, but the contemplative articulation of a model into code is authoring to me. The better we can communicate the underlying model, the better the system can grow. Indeed the ability of the system to develop is coupled to our <em>shared</em> mental model about the system.</p> <p>Often a model is communicated by using graphical- or diagram techniques. But no single diagram type covers all aspects of a software system model. Instead, we use different pictures to explain and communicate various issues of the system. The Unified Modeling Language (UML) is a standardized language that reflects this fact by providing many different diagram types, which are grouped into the structure- and behavior diagrams.</p> <blockquote> <p>In case you are a business domain expert, software developer, requirements engineer, tester or architect – do you know your UML diagram types?</p> </blockquote> <p>UML diagrams have their value, but only if the ones who work with them have a shared understanding of how to read and write this language. If specialists only use the charts for special meanings and sometimes just being created and consumed by the same single author, they do not foster communication among different members (with different skills) of a software development project but instead, have the opposite effect, because</p> <ul> <li>they are not understood well enough or</li> <li>they are not up to date because their creation is too time-consuming or</li> <li>the software to maintain and read the diagrams is not available to all project members.</li> </ul> <p>Therefore the usage of the UML diagrams should be decided with care and insight.</p> <p>The here proposed Box-Bullet-Line notation is an easy to use drop-in, that allows to</p> <ul> <li>model data flow</li> <li>see components and their dependencies</li> <li>indicate callers</li> <li>have calling sequences</li> <li>use synchronous and asynchronous communication patterns</li> <li>still be able to draw easily by hand.</li> </ul> <h2 id="dependency">Dependency</h2> <p>Let´s start with the basics. A line between two boxes indicates a dependency between two system components. A box is a component. In early phases, when you explore an existing system or design a new one when directions of communication are not of highest importance, the undirected dependency between components is a good starting point.</p> <figure> <img src="https://ulf.codes/i/blog/bbl_dependency.png" /> <figcaption>Figure: A dependency between A and B</figcaption> </figure> <h2 id="flow">Flow</h2> <p>The directed connection from A to B has the meaning of „data flow from A to B“.</p> <figure> <img src="https://ulf.codes/i/blog/bbl_flow.png" /> <figcaption>Figure: The directed connection between A and B models a data flow from A to B</figcaption> </figure> <h2 id="caller">Caller</h2> <p>The caller can be marked with a tiny bullet.</p> <figure> <img src="https://ulf.codes/i/blog/bbl_caller_push.png" /> <figcaption>Figure: A is calling B and handing over data to B</figcaption> </figure> <figure> <img src="https://ulf.codes/i/blog/bbl_caller_pull.png" /> <figcaption>Figure: B is calling A and requesting data</figcaption> </figure> <h2 id="sequences">Sequences</h2> <p>By using numbers beside the connections, calling sequences can be modeled.</p> <figure> <img src="https://ulf.codes/i/blog/bbl_caller_flow_sequence.png" /> <figcaption>Figure: Modeling data flow with a calling sequence</figcaption> </figure> <h2 id="synchronous-and-asynchronous">Synchronous and asynchronous</h2> <p>Synchronous and asynchronous communication can be modeled with single and doubled connections.</p> <figure> <img src="https://ulf.codes/i/blog/bbl_sync.png" /> <figcaption>Figure: A request initiated by A, synchronous communication. If A writes first and gets a response or A reads first and writes back is not defined.</figcaption> </figure> <figure> <img src="https://ulf.codes/i/blog/bbl_async.png" /> <figcaption>Figure: A call initiated by A, giving data to B. The asynchronous response with data from B follows.</figcaption> </figure> <p>This simple Box-Bullet-Line notation can grow with your needs. For example, you can start modeling only undirected connections, add data flow by giving your relationships a direction and extend even more by adding caller indication with calling sequences later. You can also use a swim-lane structure and place the components into those lanes, to communicate tags or domains that the components belong to.</p> <figure> <a href="https://ulf.codes/assets/bbl.pdf"><img src="https://ulf.codes/i/blog/bbl_model_natural.jpg" /></a> <figcaption>Click on the above image to get a short presentation of the BBL concepts.</figcaption> </figure> Thu, 14 Apr 2011 00:00:00 +0000 https://ulf.codes/bbl https://ulf.codes/bblthoughts A Sprint is not a milestone <p>By using Scrum, we deliver “things” in a rhythm that is given by so-called Sprints. Sprints should be of the same duration (for example two weeks) and at each Sprint ending there should be testable results. In the case of software development preferably working program code.</p> <p>Usually, a development team has not only a concept for the things to deliver in the current Sprint. A rough idea for the delivery order of the next couple of Sprints can often be seen.</p> <p>In organizations that are new to the concept of Sprints, this foresighted order can lead to the misunderstanding that Sprints need to be handled like milestones which define anticipated results of the project. This is a distorted understanding, and it makes the handling of Sprints for both – the Scrum team and the surrounding organization – difficult because it points into the wrong direction.</p> <h2 id="these-are-the-problems">These are the problems</h2> <ul> <li><strong>Reporting:</strong> The schedule and the achievement of milestones is reported to the organization, generally because other parties depend on these milestones to synchronize their work. In the case of „Sprint milestones“ we produce a chain of many milestones with short periods in between. If the Scrum team has a rough plan for the next three Sprints, but not for the subsequent ones, management tends to ask for further milestones until the end of the project. This forces the Scrum team to make an upfront project plan with Sprint milestones spanning the entire project duration. Of course, milestones need to be tracked because decisions will be made if the desired milestone achievements are not reached. Following that path, step by step the Scrum team will bring itself into a planning and reporting mode that does not help the team to deliver better and that does not support the organization to organize better. It merely produces more reporting and more reporting meetings.</li> <li><strong>Inspect and adapt:</strong> Even though I don´t think any project has so many milestones, this understanding of software development as a defined process we can cope with by detailed upfront planning is precisely what we do not want to have. The real problem of Sprint milestones is in the denial of self-organizational forces. We want to leverage these forces by using transparency, inspection, and adaption. The possibility and necessity of continuous adjustment are what lets us learn and gain insights from our doing. The upfront Sprint milestone list will make inspect and adapt more difficult and therefore will make learning more expensive, it ignores the delivery velocity of the Scrum team and negates self-organizational forces. And it sometimes leads to the Scrumfall which is also a pattern to avoid.</li> <li><strong>Scrumfall:</strong> In a Scrumfall the phases of the waterfall model are being organized into several subsequent Sprints. So you could have a first Sprint with requirements engineering, a second with analysis and design, next one implementation followed by a test Sprint and finally delivery. This is an anti-pattern, and we should understand that by following this working model the learning – which is an inherent part of any software development endeavor – is mostly being postponed to the last Sprint when we will see the final software result. Instead in Scrum, we want to go through all of the waterfall phases in each Sprint and deliver software, value, and outcome within each Sprint while learning to achieve better.</li> </ul> <blockquote> <p>A Sprint is a sensor, not a milestone.</p> </blockquote> <p>The Sprint allows us to produce small, understandable and controllable results. And it enables us to inspect in relatively short feedback cycles how good we are doing. We can learn something from each finished Sprint and a Sprint without the achievement of desired software results may be a success, because we learned an important thing to do differently in the next Sprint.</p> <p>And in the same sense a Sprint should be reported to the organization: As a sensor that tells us what is. A sensor that allows us to see, what has been done, what impediments are in our way and how we did better in comparison to previous Sprints.</p> Sat, 09 Apr 2011 00:00:00 +0000 https://ulf.codes/thoughts/a-sprint-is-not-a-milestone/ https://ulf.codes/thoughts/a-sprint-is-not-a-milestone/thoughts