<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lukas Trumm</title>
    <description>The latest articles on DEV Community by Lukas Trumm (@lttr).</description>
    <link>https://dev.to/lttr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F517706%2F1e64d30b-9f3b-4749-a513-7a037a71ee75.jpg</url>
      <title>DEV Community: Lukas Trumm</title>
      <link>https://dev.to/lttr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lttr"/>
    <language>en</language>
    <item>
      <title>Making sense of Web features</title>
      <dc:creator>Lukas Trumm</dc:creator>
      <pubDate>Thu, 12 Sep 2024 00:00:00 +0000</pubDate>
      <link>https://dev.to/lttr/making-sense-of-web-features-lo4</link>
      <guid>https://dev.to/lttr/making-sense-of-web-features-lo4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6nf7hl5l3kvo95s9fat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6nf7hl5l3kvo95s9fat.png" alt="A dashboard listing newly awailable features on the web in 2024" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is a huge amount of features on the web. The Browser Compatibility Data project lists more than 14000 of them! How to make sense of it all?&lt;/p&gt;

&lt;p&gt;This is a question that has been unanswered for a long time. Yes, every web developer uses &lt;a href="https://caniuse.com/" rel="noopener noreferrer"&gt;caiuse.com&lt;/a&gt;. Or they google or maybe ask chatgpt. The problem is that these tools have answers to specific questions, but lack a bigger picture or links to the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The WebDX Group
&lt;/h2&gt;

&lt;p&gt;Not anymore! The WebDX group is now doing an incredible job of organizing, categorizing, and naming things (← this is the hard part, as you know) around the web platform. They are trying to improve the overall developer experience with the web and browsers in a coordinated way.&lt;/p&gt;

&lt;p&gt;WebDX is a community group that is part of the W3C. You can see what they are cooking in their &lt;a href="https://github.com/web-platform-dx" rel="noopener noreferrer"&gt;repositories&lt;/a&gt;. The most interesting output for me is the &lt;a href="https://github.com/web-platform-dx/web-features" rel="noopener noreferrer"&gt;web-features repo&lt;/a&gt;. What they have done is to categorize a huge amount of specific features into a more understandable set of higher level features.&lt;/p&gt;

&lt;p&gt;For example, one of the newly available features is &lt;em&gt;Set methods&lt;/em&gt;. Any new method for manipulating a set could be a single feature. However, it becomes much more useful if it is communicated and documented as a single high-level feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The documentation
&lt;/h2&gt;

&lt;p&gt;The other part is how to find detailed information about &lt;em&gt;a feature&lt;/em&gt;. Well, this is where the &lt;a href="https://openwebdocs.org/" rel="noopener noreferrer"&gt;Open Web Docs&lt;/a&gt; initiative came in. While MDN has always been a great reference, there has been a lack of hands-on content. The Open Web Docs group is trying to change that. They are cranking out a ton of new tutorials, guides, and explainers for MDN web documentation, as well as updates to the underlying data — &lt;a href="https://github.com/mdn/browser-compat-data" rel="noopener noreferrer"&gt;BCD (Browser Compat Data)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;One example is a page on MDN about &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_colors/Relative_colors" rel="noopener noreferrer"&gt;Relative colors&lt;/a&gt;. It is cleanly mapped to a high-level web feature. It provides much better understanding and context around that feature than the individual reference pages for each color feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  The surveys
&lt;/h2&gt;

&lt;p&gt;What is really nice about the above effort is that they really want to collaborate. They take input from surveys like &lt;a href="https://stateofhtml.com/" rel="noopener noreferrer"&gt;The State of HTML&lt;/a&gt; and &lt;a href="https://stateofcss.com/" rel="noopener noreferrer"&gt;The State of CSS&lt;/a&gt;, and later they can use the same set of names for web features to track survey results about them.&lt;/p&gt;

&lt;p&gt;And by the way, while you are filling out these surveys, you can click the “Add to Reading List” button. It will present you with links to MDN where you can learn more about exactly the things you didn’t know.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality
&lt;/h2&gt;

&lt;p&gt;Great, but is the Web getting better? Hell, yes it is!&lt;/p&gt;

&lt;p&gt;The initiative to close the gap between desired features and actual availability across browsers is evident. Namely, the &lt;a href="https://wpt.fyi/interop-2024" rel="noopener noreferrer"&gt;Interop&lt;/a&gt; project ensures that a set of features is implemented as fully as possible in all major browsers. There is a new iteration of this project every year.&lt;/p&gt;

&lt;p&gt;How much and how well these features are implemented is measured using Web Platform Tests. The same set of tests is run against all browsers. That is why we have these nice percentages that reflect the actual state of the features in the browsers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Baseline
&lt;/h2&gt;

&lt;p&gt;The moment when a feature is implemented in all major browsers is a very important moment. And since we have nicely grouped the features as described above - the only thing missing is a name for the moment. And there we have it: A feature is Baseline Newly available when it is supported by all major browsers. And a feature is Widely available when two and a half years have passed since it was Newly available.&lt;/p&gt;

&lt;p&gt;You can read more about the &lt;a href="https://web.dev/baseline/" rel="noopener noreferrer"&gt;Baseline idea on web.dev&lt;/a&gt; since it was initiated by Google.&lt;/p&gt;

&lt;h2&gt;
  
  
  The visual dashboards
&lt;/h2&gt;

&lt;p&gt;Everything starts to make more sense when you can see it in a more visual way. Well-designed tables, graphs, handy links to resources right there…&lt;/p&gt;

&lt;p&gt;This is baked into a few attempts to create useful dashboards. Check them all out, each one is a different take on the subject:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://web-platform-dx.github.io/web-features-explorer/" rel="noopener noreferrer"&gt;Simple dashboard from the folks behind the WebDX group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webstatus.dev/" rel="noopener noreferrer"&gt;Nice graphs of passing web platform tests feature by feature by Google Chrome team&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;and &lt;a href="https://web-features.lttr.cz/" rel="noopener noreferrer"&gt;my attempt to create a more interactive version&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can use them from time to time to catch up on what is new in general or what is new in the Wide adoption status. It is also a good reference when you are starting a new project and deciding what set of features is actually available and supported enough.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w14l9c2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/web-features-explorer.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w14l9c2V--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/web-features-explorer.webp" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Web Features Explorer display the information in a clean way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---47rnPyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/webstatus.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---47rnPyM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/webstatus.webp" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Webstatus.dev shows real progress on features in terms of passed web platform tests in graphs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5YkTn-4g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/web-platform-features.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5YkTn-4g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://lukastrumm.com/blog/making-sense-of-web-features/web-platform-features.webp" width="800" height="600"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My Web Platform Features dashboard allows filtering and sorting features&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The future
&lt;/h2&gt;

&lt;p&gt;Some features have recently been implemented in all browsers rather quickly. But some may not even be considered a good idea by some browser makers. You can find detailed information about what may or may not be coming at the following sites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://mozilla.github.io/standards-positions/" rel="noopener noreferrer"&gt;Mozilla standards positions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://webkit.org/standards-positions/" rel="noopener noreferrer"&gt;Webkit team standards positions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chromestatus.com/roadmap" rel="noopener noreferrer"&gt;Google Chrome feature roadmap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Watching the web platform evolve is fascinating. The feedback loop is improving. Interoperability is getting better in many areas.&lt;/p&gt;

&lt;p&gt;I have wanted to have a useful dashboard with web features for a long time, and suddenly the data is of such nice quality that I managed to build &lt;a href="https://web-features.lttr.cz/" rel="noopener noreferrer"&gt;my own&lt;/a&gt; in a couple of evenings.&lt;/p&gt;

</description>
      <category>web</category>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Working with correct versions of tools in the JavaScript ecosystem</title>
      <dc:creator>Lukas Trumm</dc:creator>
      <pubDate>Mon, 03 Apr 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/lttr/working-with-correct-versions-of-tools-in-the-javascript-ecosystem-25bc</link>
      <guid>https://dev.to/lttr/working-with-correct-versions-of-tools-in-the-javascript-ecosystem-25bc</guid>
      <description>&lt;p&gt;The ideal is to have the desired version of every tool at every situation during both development and deployment. Docker might be the answer for someone, but it might not be practical to use it all the time. Let’s analyze the situation.&lt;/p&gt;

&lt;p&gt;There is an initiative called &lt;a href="https://containers.dev/"&gt;devcontainers&lt;/a&gt; to improve the practicality of the docker solution, but I’m not going to discuss that in this article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions
&lt;/h2&gt;

&lt;p&gt;By &lt;strong&gt;tool,&lt;/strong&gt; I mean the runtime (like &lt;code&gt;nodejs&lt;/code&gt;), package manager (like &lt;code&gt;pnpm&lt;/code&gt;), and others (&lt;code&gt;docker&lt;/code&gt;, &lt;code&gt;git&lt;/code&gt;, and other CLI tools).&lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;situation,&lt;/strong&gt; I mean running your first command after &lt;code&gt;git clone&lt;/code&gt;, running a command after switching &lt;code&gt;git branch&lt;/code&gt;, or running a command in a &lt;code&gt;CI/CD&lt;/code&gt; pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  There are several levels of perfection
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Nothing. When something breaks, someone might fix it.&lt;/li&gt;
&lt;li&gt;Documentation. &lt;a href="http://readme.md/"&gt;README.md&lt;/a&gt;. After following the docs carefully, a developer should be on the correct version of tools. Extra communication is necessary when updating versions.&lt;/li&gt;
&lt;li&gt;Enforcement. There is configuration in place which forces certain tool versions and refuses to operate otherwise.&lt;/li&gt;
&lt;li&gt;Automagic. The environment (either local or in CI) is set up in such a way, that it automatically uses (and installs before) correct versions of tools as configured. Might be harder to achieve without extra maintenance and documentation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Based on these options, I think there is no ideal solution.&lt;/p&gt;

&lt;p&gt;For small or personal projects (1) may be enough. For projects, that are not actively developed, (2) may be appropriate. When issues with incorrect versions occurs, it is time to make some safeguards (3). For larger teams or larger amount of projects per developer, it might be beneficial to invest into automation (4).&lt;/p&gt;

&lt;h2&gt;
  
  
  How to
&lt;/h2&gt;

&lt;p&gt;A lot of the times it is enough to specify the major version. Like &lt;code&gt;node 18&lt;/code&gt;, &lt;code&gt;yarn 1&lt;/code&gt; etc. I personally run into most issues because of switching between projects that uses different major versions of tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the correct version in CI/CD
&lt;/h3&gt;

&lt;p&gt;CI/CD needs to be configured in code, ideally in the same repo as the rest of the application code. That way, the definition of versions are closer between local and production environment. One might choose to use &lt;code&gt;docker&lt;/code&gt; to make sure, that the whole environment is the same, but it is not always practical (might be slower for local development, might not fit the app architecture, might require unnecessary know-how).&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the correct version of the runtime
&lt;/h3&gt;

&lt;p&gt;I will focus on &lt;code&gt;nodejs&lt;/code&gt; versions. One might soon need to deal with other runtimes like &lt;code&gt;deno&lt;/code&gt; or &lt;code&gt;bun&lt;/code&gt;, but leave that for another time.&lt;/p&gt;

&lt;p&gt;To enforce a valid version you can use the &lt;code&gt;engines&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That will inform you about wrong version, but it does not do anything about it. What you want is a tool that installs and/or switches to the correct version whenever you switch directories on your command line.&lt;/p&gt;

&lt;p&gt;First, you configure the desired version. Something like this (I use this with &lt;code&gt;fnm&lt;/code&gt;, but different tools need different configuration):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .node-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then setup a tool and your command line shell. Some options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/Schniz/fnm"&gt;fnm&lt;/a&gt; is simple&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.volta.sh/"&gt;volta&lt;/a&gt; can manage node, package manager and other tools from NPM&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://asdf-vm.com/"&gt;asdf&lt;/a&gt; is good when you need to handle more languages&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use the correct package manager
&lt;/h3&gt;

&lt;p&gt;You can go far with a set of shell aliases or functions. I have recently switched to using &lt;a href="https://github.com/antfu/ni"&gt;@antfu/ni&lt;/a&gt; and it is way better. You can stop warring about the package manager a given project is using from now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the correct version of the package manager
&lt;/h3&gt;

&lt;p&gt;This is more tricky, but using the &lt;code&gt;engines&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt; can enforce a version range.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=18"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pnpm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;gt;=7"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Corepack (mentioned below) should improve this point in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the correct versions of formatting, linting and building tools
&lt;/h3&gt;

&lt;p&gt;Define them as &lt;code&gt;devDependencies&lt;/code&gt; and use them via &lt;code&gt;scripts&lt;/code&gt;. Like &lt;code&gt;nr build&lt;/code&gt; from &lt;code&gt;@antfu/ni&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Careful about running them ad hoc, there are a lot of details behind commands like &lt;code&gt;npm exec&lt;/code&gt;, &lt;code&gt;npm x&lt;/code&gt;, &lt;code&gt;npx&lt;/code&gt; , &lt;code&gt;pnpm dlx&lt;/code&gt;, &lt;code&gt;pnpm exec&lt;/code&gt;, …&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives and the future
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Helper NPM packages
&lt;/h3&gt;

&lt;p&gt;There are NPM packages that might help (e.g. &lt;a href="https://github.com/pnpm/only-allow"&gt;only-allow&lt;/a&gt;). The problem is that it might not work all the time (looking at GitHub issues…) and it is an extra dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Package manager policies
&lt;/h3&gt;

&lt;p&gt;If you are using &lt;code&gt;yarn&lt;/code&gt; a lot, it might be worth looking it its version enforcement solution, which is &lt;a href="https://classic.yarnpkg.com/en/docs/cli/policies/#toc-policies-set-version"&gt;documented here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Corepack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/api/corepack.html"&gt;Corepack&lt;/a&gt; probably will be the way to go—it will manage the versions of package managers for you, using &lt;code&gt;"packageManager"&lt;/code&gt; field in &lt;code&gt;package.json&lt;/code&gt;. It is still experimental and various tools might not work with it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The JavaScript ecosystem is moving fast. If you want to be up to date you need tooling that help you keep your sanity. With tooling that I have described in this article, you can forget about some aspects of dependency management—and that is a good thing.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>77+ questions about a web project</title>
      <dc:creator>Lukas Trumm</dc:creator>
      <pubDate>Wed, 08 Feb 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/lttr/77-questions-about-a-web-project-2396</link>
      <guid>https://dev.to/lttr/77-questions-about-a-web-project-2396</guid>
      <description>&lt;p&gt;&lt;em&gt;You were asked to build a website? Does it seem it will be a larger one? It might be the case it will actually not be a website but a webapp. It might need a team to actually do it. Well, better prepare answers for these couple of questions :-)&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Table of content
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vision and requirements&lt;/li&gt;
&lt;li&gt;Communication&lt;/li&gt;
&lt;li&gt;Technical environment&lt;/li&gt;
&lt;li&gt;Infrastructure&lt;/li&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;li&gt;Code&lt;/li&gt;
&lt;li&gt;Runtime&lt;/li&gt;
&lt;li&gt;SEO&lt;/li&gt;
&lt;li&gt;Performance, UX, a11y&lt;/li&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Legal&lt;/li&gt;
&lt;li&gt;Maintenance&lt;/li&gt;
&lt;li&gt;Marketing and sales&lt;/li&gt;
&lt;li&gt;The bottom line&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Vision and requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is there a short document &lt;strong&gt;explaining why&lt;/strong&gt; this piece of software should exist and a concise description how it would accomplish that?&lt;/li&gt;
&lt;li&gt;Do we have a place for &lt;strong&gt;collecting and prioritizing&lt;/strong&gt; requirements?&lt;/li&gt;
&lt;li&gt;Are &lt;strong&gt;non-functional requirements&lt;/strong&gt; written somewhere?&lt;/li&gt;
&lt;li&gt;Do we have a &lt;strong&gt;schedule&lt;/strong&gt; or milestones which describes at least roughly what will be done when?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Communication
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Can you think of any &lt;strong&gt;expectations&lt;/strong&gt; that are not described by current requirements?&lt;/li&gt;
&lt;li&gt;Will the &lt;strong&gt;customer collaborate&lt;/strong&gt; with us on a regular basis?&lt;sup&gt;[1]&lt;/sup&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Technical environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Does anyone from the team have a specific &lt;strong&gt;know-how&lt;/strong&gt; which is necessary / effective to leverage for successful completion of the project?&lt;/li&gt;
&lt;li&gt;Will there be a reasonable return of investment from &lt;strong&gt;learning&lt;/strong&gt; and implementing new technologies? Would it be easier to hire new people with such skills?&lt;/li&gt;
&lt;li&gt;Are there &lt;strong&gt;existing systems&lt;/strong&gt; like CMSes or APIs that needs to be integrated?&lt;/li&gt;
&lt;li&gt;Are there existing URL addresses or domains that needs to be &lt;strong&gt;redirected&lt;/strong&gt; to new ones once the new website will be released?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is there a possibility that currently running systems will be negatively impacted after deploying this new application on target domain?&lt;/li&gt;
&lt;li&gt;How will we &lt;strong&gt;host&lt;/strong&gt; our website or application? Is it possible to change it now or in the future?&lt;/li&gt;
&lt;li&gt;What are the pros and cons of chosen hosting environment over some more traditional choice?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Users
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Do we have some existing &lt;strong&gt;analytics data&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How many users&lt;/strong&gt; do we expect first day, first month, first year?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;browsers&lt;/strong&gt; and their versions are going to be supported?&lt;/li&gt;
&lt;li&gt;Would the project suffer from missing &lt;strong&gt;accessibility&lt;/strong&gt; features? Is it a subject of regulation?&lt;/li&gt;
&lt;li&gt;Is it any good to provide users with a &lt;strong&gt;chatbot&lt;/strong&gt; and is it worth the effort and possible performance issues?&lt;/li&gt;
&lt;li&gt;Are there any use cases for our website/application to be used &lt;strong&gt;without JavaScript&lt;/strong&gt; enabled?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is/will not be in a &lt;strong&gt;version control&lt;/strong&gt; system? (like secrets, documents, etc.)&lt;/li&gt;
&lt;li&gt;Is there a &lt;strong&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/strong&gt; file which has enough information for any developer to run the application, test it or prepare it for production?&lt;/li&gt;
&lt;li&gt;Does every developer have an automatic way of &lt;strong&gt;formatting&lt;/strong&gt; new code? (in editor on save, precommit hook)&lt;/li&gt;
&lt;li&gt;Is there a process in CI that checks common code &lt;strong&gt;style issues&lt;/strong&gt; for every change? (i.e. linting)&lt;/li&gt;
&lt;li&gt;Is there a process in place that ensures that all code is &lt;strong&gt;checked for quality&lt;/strong&gt;? (code reviews, automated tests and checks)&lt;/li&gt;
&lt;li&gt;Does every developer know when and how a code review is needed and when it is appropriate to merge? &lt;sup&gt;[2]&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Are there some automated &lt;strong&gt;checks for security&lt;/strong&gt;? &lt;sup&gt;[3]&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Is there a &lt;strong&gt;CI/CD&lt;/strong&gt; pipeline that deploys every change? (continuous deployment)&lt;/li&gt;
&lt;li&gt;Is there a &lt;strong&gt;preview environment&lt;/strong&gt; for every change and is it practical to have them?&lt;/li&gt;
&lt;li&gt;Do we have know-how when and how to use unit &lt;strong&gt;testing&lt;/strong&gt; , integration testing or end-to-end testing?&lt;/li&gt;
&lt;li&gt;Do we use the right programming &lt;strong&gt;language&lt;/strong&gt; for the job?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;framework&lt;/strong&gt; do we use, what it solves and what problems it does not solve?&lt;/li&gt;
&lt;li&gt;Is there a way to &lt;strong&gt;generate&lt;/strong&gt; some boring boilerplate code?&lt;/li&gt;
&lt;li&gt;Do we have a set of &lt;strong&gt;testing data&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Can we develop against this data set without even running the database?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Runtime
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Does the web app handle &lt;strong&gt;redeployments&lt;/strong&gt; of static assets seamlessly?&lt;/li&gt;
&lt;li&gt;How will the web app handle a breaking &lt;strong&gt;change in backend APIs&lt;/strong&gt; while an old version of frontend code is still running on the client side?&lt;/li&gt;
&lt;li&gt;How is the cache on the &lt;strong&gt;CDN&lt;/strong&gt; level invalidated?&lt;/li&gt;
&lt;li&gt;Do we send correct &lt;strong&gt;security headers&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Do we send correct &lt;strong&gt;cache&lt;/strong&gt; headers for HTML, data requests and assets?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  SEO
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Does every page have its &lt;strong&gt;canonical URL&lt;/strong&gt;? &lt;sup&gt;[4]&lt;/sup&gt;
&lt;/li&gt;
&lt;li&gt;Does our canonical URLs end with or without a slash? Do all redirects, sitemap items and links target this canonical URL?&lt;/li&gt;
&lt;li&gt;Do our domain default to &lt;strong&gt;www&lt;/strong&gt; prefix?&lt;/li&gt;
&lt;li&gt;Do we need more control over Google results, and will we use Google search console? Will we use structured data?&lt;/li&gt;
&lt;li&gt;Which website &lt;strong&gt;analytics&lt;/strong&gt; solution will be used? Will we try to project for missing data (blocked by users or usage before consent) and how?&lt;/li&gt;
&lt;li&gt;Do we have a complete &lt;strong&gt;sitemap&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Do we have a &lt;strong&gt;robots.txt&lt;/strong&gt;? Does it contain only necessary records?&lt;/li&gt;
&lt;li&gt;Do we have a page on the site for every frequent &lt;strong&gt;search term&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How are we managing &lt;strong&gt;third party scripts&lt;/strong&gt;? Do we need Google Tag Manager? How much will be the performance influenced by third party scripts?&lt;/li&gt;
&lt;li&gt;Does the application respond with correct &lt;strong&gt;response codes&lt;/strong&gt;? An unknown URL should be 404 etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Performance, UX, a11y
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is it OK to display &lt;strong&gt;loading spinners&lt;/strong&gt; for 10 seconds on a 3G network before displaying the content?&lt;/li&gt;
&lt;li&gt;Will we have to do &lt;strong&gt;image preprocessing&lt;/strong&gt;? Will it be a hosted solution? Do we care about resolutions and formats of those shipped images?&lt;/li&gt;
&lt;li&gt;Is it useful to measure &lt;strong&gt;Core web vitals&lt;/strong&gt; regularly/automatically?&lt;/li&gt;
&lt;li&gt;Will we use &lt;strong&gt;progressive enhancement&lt;/strong&gt; techniques? Does our team have knowledge to do so?&lt;/li&gt;
&lt;li&gt;Are we going to optimize the amount of &lt;strong&gt;generated CSS&lt;/strong&gt;? How?&lt;/li&gt;
&lt;li&gt;Can be the desired set of fonts optimized in order to prevent &lt;em&gt;Flash of unstyled fonts&lt;/em&gt; for most users?&lt;/li&gt;
&lt;li&gt;Which level of &lt;strong&gt;accessibility&lt;/strong&gt; will be our target? Do we have someone who understands accessibility on this level?&lt;/li&gt;
&lt;li&gt;Do we have a plan for hallway &lt;strong&gt;usability testing&lt;/strong&gt;?&lt;sup&gt;[5]&lt;/sup&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How does our &lt;strong&gt;design process&lt;/strong&gt; look like? How are responsibilities distributed among designers, developers, marketers, product or UX people?&lt;/li&gt;
&lt;li&gt;Do we need our own &lt;strong&gt;design system&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;tools and techniques&lt;/strong&gt; we will use (preprocessing, postprocessing, feature detection, polyfills, CSS structure and layering, scoping, reset, RTL support…)?&lt;/li&gt;
&lt;li&gt;How will we approach responsive design? &lt;strong&gt;Mobile or desktop first&lt;/strong&gt; , strict set of media queries or more fluid techniques, leverage container queries?&lt;/li&gt;
&lt;li&gt;Which &lt;strong&gt;set of icons&lt;/strong&gt; we will use? Will it play well with our framework of choice?&lt;/li&gt;
&lt;li&gt;Do we have a live web with our &lt;strong&gt;style guide&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Legal
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Is it necessary to have a &lt;strong&gt;cookie consent&lt;/strong&gt; on the website?&lt;/li&gt;
&lt;li&gt;In case we need a cookie consent would it be beneficial to use a third party solution? Will we use the analytics from that solution for something?&lt;/li&gt;
&lt;li&gt;Do we need to implement something extra in order to comply with &lt;strong&gt;privacy laws&lt;/strong&gt; like GDPR?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Maintenance
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Where will we &lt;strong&gt;track tasks and bugs&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How can our &lt;strong&gt;customers report&lt;/strong&gt; bugs?&lt;/li&gt;
&lt;li&gt;Do we have an automated system for &lt;strong&gt;reporting runtime errors&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;How are our production systems &lt;strong&gt;backuped&lt;/strong&gt;? When was the last time we have done a restoration from those backups?&lt;/li&gt;
&lt;li&gt;How often there is a change in some data or source code? For how long will our system handle the increasing frequency of change?&lt;/li&gt;
&lt;li&gt;Which types of changes would our &lt;strong&gt;architecture&lt;/strong&gt; allow easily and which would be hard?&lt;/li&gt;
&lt;li&gt;Do we have a place for writing down &lt;strong&gt;maintenance procedures&lt;/strong&gt;? (E.g. updating dependencies, data schema migration, adding redirects, etc.)&lt;/li&gt;
&lt;li&gt;Who manages credentials and how? Do we need to use an external service for them? Do we need to rotate them?&lt;/li&gt;
&lt;li&gt;Is there a single place (like a URL) which anybody from the team can visit and see important links or other useful information about the project? (I call this a &lt;strong&gt;project signpost&lt;/strong&gt; )&lt;/li&gt;
&lt;li&gt;Do we need to track special events in the system, like &lt;strong&gt;conversions&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Do we have a way to automatically check for links that accidentally targets &lt;strong&gt;PAGE NOT FOUND&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Does our &lt;strong&gt;monitoring, logging&lt;/strong&gt; and tracking solution solve real problems?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Marketing and sales
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How does marketing or sales strategy correspond to a &lt;strong&gt;release date&lt;/strong&gt; of our product?&lt;/li&gt;
&lt;li&gt;Do we focus enough on &lt;strong&gt;feedback&lt;/strong&gt; from users, developers, investors?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;This is not an exhaustive list, although I was trying to be complete—based on my experience. BUT keep in mind that it is also critical to &lt;strong&gt;maximize the amount of work that does not need to be done!&lt;/strong&gt; &lt;sup&gt;[6]&lt;/sup&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Notes
&lt;/h4&gt;

&lt;ol&gt;
&lt;li id="fn1"&gt;
&lt;p&gt;From &lt;a href="https://agilemanifesto.org/" rel="noopener noreferrer"&gt;Agile manifesto&lt;/a&gt;:
Customer collaboration over contract negotiation ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn2"&gt;
&lt;p&gt;One nice strategy for this is called &lt;a href="https://martinfowler.com/articles/ship-show-ask.html" rel="noopener noreferrer"&gt;Ship / Show /
Ask&lt;/a&gt; ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn3"&gt;
&lt;p&gt;For example GitHub has tools for automated checks of
&lt;a href="https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates" rel="noopener noreferrer"&gt;dependencies&lt;/a&gt;
and &lt;a href="https://github.com/github/codeql-action" rel="noopener noreferrer"&gt;static code analysis&lt;/a&gt; ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn4"&gt;
&lt;p&gt;There are quite a few rules for canonical URLs so it is best
to consult &lt;a href="https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls" rel="noopener noreferrer"&gt;Google search
documentation&lt;/a&gt; ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn5"&gt;
&lt;p&gt;Hallway usability testing is mentioned for example
in the famous &lt;a href="https://www.joelonsoftware.com/2000/08/09/the-joel-test-12-steps-to-better-code/" rel="noopener noreferrer"&gt;Joel’s
test&lt;/a&gt; ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;li id="fn6"&gt;
&lt;p&gt;Again a quote from &lt;a href="https://agilemanifesto.org/" rel="noopener noreferrer"&gt;Agile
manifesto&lt;/a&gt; ↩︎&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>robotics</category>
      <category>howto</category>
      <category>vibecoding</category>
      <category>coding</category>
    </item>
    <item>
      <title>Power management on Ubuntu and Pop!_OS</title>
      <dc:creator>Lukas Trumm</dc:creator>
      <pubDate>Wed, 16 Dec 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/lttr/power-management-on-ubuntu-and-pop-os-kg5</link>
      <guid>https://dev.to/lttr/power-management-on-ubuntu-and-pop-os-kg5</guid>
      <description>&lt;p&gt;Is it possible to hibernate a Linux machine? What is the difference between sleep, suspend, stand-by and hibernation? Why isn’t my machine waking up after pressing keys on my keyboard?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JYMBteuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lukastrumm.com/img/will-it-sleep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JYMBteuX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://lukastrumm.com/img/will-it-sleep.png" alt=""&gt;&lt;/a&gt;What is going to happen?&lt;/p&gt;

&lt;p&gt;I can finally answer these questions after a long time wondering why something does not work. Let me explain some of the concepts first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power management concepts #
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;These concepts are general but what I’m describing here might be specific for Ubuntu based Linux systems.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sleep and suspend #
&lt;/h3&gt;

&lt;p&gt;These terms are used interchangeably. The state of your machine is saved to RAM and the computer puts as much as it can to some low power consumption mode. Energy is still consumed and there is a risk of losing unsaved work in case energy is no longer available (e.g. empty battery). The advantage is, that suspending and waking up is fast (couple of seconds in my experience).&lt;/p&gt;

&lt;h3&gt;
  
  
  Hibernate #
&lt;/h3&gt;

&lt;p&gt;When a computer hibernates it saves its state to hard drive and then shuts down. Someone might call it &lt;em&gt;suspend to disk&lt;/em&gt;. When it wakes up it restores its state from hard drive into memory. You need space on your hard drive in other to save the state.&lt;/p&gt;

&lt;p&gt;Hibernation has most issues, probably because it is dependant on the combination of hardware and operating system. You might not need hibernation—sleep might save enough energy and power off might be fast enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Power off #
&lt;/h3&gt;

&lt;p&gt;Is a normal process of properly shutting down a computer. &lt;em&gt;Halting&lt;/em&gt; a computer might be slightly different. As I understand it &lt;em&gt;powering off&lt;/em&gt; is a more complete process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lock screen #
&lt;/h3&gt;

&lt;p&gt;When you manually lock your computer or when you are away for some time it provides you with a prompt for password—your computer is locked. The same happens when the computer is waking up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Log out #
&lt;/h3&gt;

&lt;p&gt;Shuts down your running applications (it might not stop all of the background processes) and effectively locks the screen.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idle time #
&lt;/h3&gt;

&lt;p&gt;Is a time when the computer evaluates that it is doing nothing. From the practical point of view the computer can be configured to do something useful after some specific time of beiing idle and it might lock the screen or suspend itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Standby and awake #
&lt;/h3&gt;

&lt;p&gt;I believe you can’t directly force your computer to go into those states, those are probably internal. In &lt;em&gt;awake&lt;/em&gt; state all components are running, while in &lt;em&gt;standby&lt;/em&gt; state harddisks and other peripherials might be turned off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shutting down #
&lt;/h2&gt;

&lt;p&gt;Or rather sleeping down because at least for me, suspending is way more convenient (read: faster) way of ending my work. I usually hit a dedicated key on my keyboard (a cheep Cherry keyboard). Another way is to let your machine sleep after a specific time. In Gnome settings there is an item called Automatic suspend (Settings ➙ Power), where you can set it up. Wierdly enough you need Gnome Tweaks to set the suspend action after closing a lid of your notebook (it is in General section there).&lt;/p&gt;

&lt;h2&gt;
  
  
  Waking up #
&lt;/h2&gt;

&lt;p&gt;A reasonable way to wake up your computer is to hit some key on a keyboard. It might sound simple, but there are issues with external keyboards for notebooks or wireless keyboards. In my case I have checked &lt;a href="https://askubuntu.com/"&gt;askUbuntu&lt;/a&gt; and my BIOS settings and found a disabled option. Now I can wake up my notebook (from sleep) using keyboard (not mouse—but I like it) which is connected via USB dongle.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources #
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/369760/what-are-the-differences-between-sleep-standby-suspend-and-hibernate-in-ubuntu"&gt;https://askubuntu.com/questions/369760/what-are-the-differences-between-sleep-standby-suspend-and-hibernate-in-ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://askubuntu.com/questions/848698/wake-up-from-suspend-using-wireless-usb-keyboard-or-mouse-for-any-linux-distro/1155666#1155666"&gt;https://askubuntu.com/questions/848698/wake-up-from-suspend-using-wireless-usb-keyboard-or-mouse-for-any-linux-distro/1155666#1155666&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/stable/ubuntu-help/power-suspend.html.en"&gt;https://help.ubuntu.com/stable/ubuntu-help/power-suspend.html.en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/stable/ubuntu-help/shell-exit.html.en#suspend"&gt;https://help.ubuntu.com/stable/ubuntu-help/shell-exit.html.en#suspend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.ubuntu.com/PowerManagement"&gt;https://wiki.ubuntu.com/PowerManagement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/stable/ubuntu-help/session-screenlocks.html.en"&gt;https://help.ubuntu.com/stable/ubuntu-help/session-screenlocks.html.en&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Flexbox zombies</title>
      <dc:creator>Lukas Trumm</dc:creator>
      <pubDate>Fri, 20 Nov 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/lttr/flexbox-zombies-18lf</link>
      <guid>https://dev.to/lttr/flexbox-zombies-18lf</guid>
      <description>&lt;p&gt;Recently I have finished the Flexbox zombies game. The way the author forces you to deliberately practice a skill is great.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://flexboxzombies.com"&gt;Flexbox zombies&lt;/a&gt; is an online course that teaches you the &lt;code&gt;display: flex&lt;/code&gt; css property. It presents quite a boring topic - placing items on a screen - in a very atractive way.&lt;/p&gt;

&lt;p&gt;Even if you think you know css flexbox I would still recommend it, because it is interesting how it is presented directly inside a browser and everything is interactive. And you will probably find out you don't know everything. I have found a couple of new facts and following are some notes about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with display: flex
&lt;/h2&gt;

&lt;p&gt;The number of times one have to write &lt;code&gt;display: flex&lt;/code&gt; in the course is overwhelming, but at the end, it was worth it. As the author said - it is about deliberate practice.&lt;/p&gt;

&lt;p&gt;Lets define a class with &lt;code&gt;display: flex&lt;/code&gt; and a couple of other properties.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.flex-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rebeccapurple&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.flex-item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;darkcyan&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Flexible width
&lt;/h2&gt;

&lt;p&gt;Width is flexible - who would guess?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.my-box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;250px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;225px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.item-1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-shrink&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.item-2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-grow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Fits the content&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item my-box"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Flex-basis wide&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item my-box item-1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;No need to shrink&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item my-box item-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Grow stops at 250px&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--m_AAZs3g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w9x375f66m4368z6g7hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--m_AAZs3g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/w9x375f66m4368z6g7hc.png" alt="Four boxes with different widths according to flex specific properties"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Flex shorthand
&lt;/h2&gt;

&lt;p&gt;Shorthand property &lt;code&gt;flex&lt;/code&gt; combines &lt;code&gt;flex-grow&lt;/code&gt;, &lt;code&gt;flex-shrink&lt;/code&gt; and &lt;code&gt;flex-basis&lt;/code&gt;. When you omit the last one, &lt;code&gt;flex-basis&lt;/code&gt; became &lt;code&gt;0&lt;/code&gt; instead of &lt;code&gt;auto&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.flex-basis-auto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.flex-basis-zero&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item flex-basis-auto"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Flex-basis auto&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item flex-basis-zero"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Flex-basis 0&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r8U0zwHQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n4ctohivleyjx2rz9d13.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r8U0zwHQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n4ctohivleyjx2rz9d13.png" alt="Two boxes, one with normal width and another with minimum width"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Align content
&lt;/h2&gt;

&lt;p&gt;In the following example the &lt;code&gt;align-content&lt;/code&gt; property pushes all the items to the vertical center of the container while &lt;code&gt;align-items&lt;/code&gt; to the center of their lines.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.content-aligned&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.items-aligned&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.content-aligned&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt;
  &lt;span class="nc"&gt;.items-aligned&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-basis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;140px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container content-aligned"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: darkcyan"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: darkgreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: cadetblue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;br&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container items-aligned"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: purple"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: darkcyan"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: darkgreen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"background: cadetblue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8riNg6XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01baq5qag87eo9jsynsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8riNg6XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01baq5qag87eo9jsynsp.png" alt="Showing the difference between align-content and align-items, where align-content aligns everything in the middle, while align-items aligns items in their lines"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  New properties
&lt;/h2&gt;

&lt;p&gt;There are new properties available in some browsers that are not mentioned in the Flexbox zombies course.&lt;/p&gt;

&lt;p&gt;One is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/gap"&gt;&lt;code&gt;gap&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.flex-with-gap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container flex-with-gap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8riNg6XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01baq5qag87eo9jsynsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8riNg6XU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/01baq5qag87eo9jsynsp.png" alt="Boxes with gap between them"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another one is &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/place-content"&gt;&lt;code&gt;place-content&lt;/code&gt;&lt;/a&gt; a shorthand for &lt;code&gt;justify-content&lt;/code&gt; and &lt;code&gt;align-content&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.flex-centered&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;flex-wrap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;wrap&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="py"&gt;place-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nc"&gt;.flex-centered&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;120px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-container flex-centered"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex-item"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Item 3&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QnESTQLo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7de441szogxo909m6ai9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QnESTQLo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7de441szogxo909m6ai9.png" alt="Both vertically and horizontally centered items in a container box"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Flexbox zombies is a great course and great game at the same time. That's rare!&lt;/p&gt;

&lt;p&gt;I don't remember if the course mentioned a very useful value of &lt;code&gt;justify-content&lt;/code&gt;: &lt;code&gt;space-evenly&lt;/code&gt;. Other than that it is very thorough. I highly recommend this style of learning!&lt;/p&gt;

&lt;p&gt;More interactive (you can live edit the code) version of &lt;a href="https://lukastrumm.com/blog/2020/flexbox-zombies/"&gt;this article&lt;/a&gt; is on my website.&lt;/p&gt;

</description>
      <category>css</category>
    </item>
  </channel>
</rss>
