View
Repeats

Auto-generating plain-text bodies for HTML e-mails in Rails apps

When building an application that sends e-mails to users, you want to avoid those e-mails from being classified as spam. Most obvious scoring issues will not be relevant to you because you are not a spammer.

However, your application must do one thing by itself: When sending HTML e-mails, you should include a plain-text body or tools like SpamAssassin will apply a significant score penalty. Here is how to do that automatically.

  1. Add premailer-rails to your Gemfile and bundle.
  2. Done! ...

A few recent CSS properties

  • Feature Queries (Edge 12+): Similar to @media queries, @supports blocks can be scoped to browsers that support a given declaration. There is CSS.supports() to do the equivalent in Javascript.

  • backdrop-filter (Edge 17+, but not FF): Applying filters to what is visible through an element.

  • [touch-action](https://d...

Variable fonts for web developers

This card is mainly an explanation how variable fonts work in CSS, not necessarily a recommendation to actually use them.

What is a variable font?

Designing and rendering fonts are two highly complex topics. For an arbitrary text to appear properly on your screen, its font must be created multiple times for different "settings" like stroke width (boldness) and style (e.g. italic).

Now as web developers, we usually ship these variants of the same font via multiple @font-faces of the same font-family:

@font-face
  font-family...
Repeats

Improving browser rendering performance

As the web is being used for more and more tasks, expectations rise. Not only should web pages offer rich interaction, they must be responsive in both size and interaction.

This imposes a paradoxon that needs to be solved by building performing applications. It's not enough any more to have your web site do crazy stuff, it is also required to do it crazy fast. This card is intended to give you an introduction to this emerging aspect of web development.

Read this introductory [performance study on Pinterest](http://www.smashingmagazine.com/...

Linked contentRepeats

Designing HTML emails

Note: Instead of building your e-mails manually as described below, you probably want to use a tool like MJML.

The 90s are calling: they want their tables back. Unfortunately, you need them all for laying out your HTML emails.

Email client HTML rendering is way more scattered than browser HTML. While you might have a pretty good understanding of what features and patterns you can use to support all major browsers, I doubt anyone masters this craft for HTML email clients.

The only way to ensure your email looks good...

Check that an element is hidden via CSS with Spreewald

If you have content inside a page that is hidden by CSS, the following will work with Selenium, but not when using the Rack::Test driver. The Selenium driver correctly only considers text that is actually visible to a user.

Then I should not see "foobear"

This is because the Rack::Test driver does not know if an element is visible, and only looks at the DOM.

Spreewald offers steps to check that an element is hidden by CSS:

Then "foo" should be hidden

You can also check that an el...

Repeats

Capybara: Find an element that contains a string

There is no CSS selector for matching elements that contains a given string ¹. Luckily, Capybara offers the :text option to go along with your selector:

page.find('div', text: 'Expected content')

You can also pass a regular expression!

page.find('div', text: /Expected contents?/i)

Note that if your CSS selector is as generic as div, you might get a lot more results than you expect. E.g. a <div class="container"> that surrounds your entire layout will probably also contain that text (in a descendant) and Capybara wil...

Linked content

Tailwind versus BEM

The linked article compares two approaches for writing CSS:

  • A component library (like BEM)
  • Utility classes (like Tailwind)

It's good to know the pros and cons of each approach. Although we default to BEM, you might encounter a utility approach in a client project.

Repeats

CSS: Combining different length units with calc()

calc() lets you mix CSS units. Ever wanted to give an element "the container's width minus 20px on each side"? Here you go:

width: calc(100% - (20px * 2));

When using Sass, you need to interpolate Sass expressions:

width: calc(100% - #{$margin})

Supported by all modern browsers and IE9+.

Repeats

Keeping web applications fast

Our applications not only need to be functional, they need to be fast.

But, to quote Donald Knuth,

premature optimization is the root of all evil (or at least most of it) in programming

The reasoning is that you should not waste your time optimizing code where it does not even matter. However, I believe there are some kinds of optimizations you should do right away, because

  • they are either obvious and easy
  • or they are very hard to do optimize later

This is an attempt to list some of those things:

On the server

...

Repeats

How to make your application assets cachable in Rails

Note: Modern Rails has two build pipelines, the asset pipeline (or "Sprockets") and Webpacker. The principles below apply for both, but the examples shown are for Sprockets.


Every page in your application uses many assets, such as images, javascripts and stylesheets. Without your intervention, the browser will request these assets again and again on every request. There is no magic in Rails that gives you automatic caching for assets. In fact, if you haven't been paying attention to this, your application is probabl...

Repeats

CSS variables aka CSS Custom Properties

CSS variables are very different from preprocessor variables. While preprocessors use variables to compile a static piece of CSS, CSS custom properties are a reactive (i.e. live) part of the styles. Think of them like usual CSS properties that cascade, but have:

  • a special syntax: CSS variables always start with a double-dash (--color)
  • no inherent meaning: Defining a CSS variable will not change any styles in itself
  • a special functionality: CSS variables can be used within the values of other properties, including CSS variables...
Linked contentRepeats

Chrome Lighthouse

Chrome has a built-in utility to check performance and accessibility (and more) of your web app: Lighthouse.

Open the Develeoper Tools and go to the lighthouse tab:

Image

Then you'll see some suggestions on how to improve your site.
This is cool, because you can even use it with non-public pages or your development environment (but be aware that some settings we're using for development, like not minifying JS and CSS files, might ruin your stats...

Repeats

Stretching an HTML page to full height

This card existed before, but was outdated due to browser implementation changes. The information below is validated for the current list of browsers we support.


By default your html and body elements are only as high as the actual page content. If you only have two lines of text in your page, your html and body elements will only be around 40 pixels high, regardless of the size of your browser window.

You might be surprised by this, since setting a background on either html and body does cover the enti...

Repeats

BEM naming conventions

We structure our CSS using the BEM pattern.

Our naming convention for blocks, elements and modifiers has evolved over the years. This card shows our current style and various alternative styles that you might encounter in older projects.

The difference between the various styles are mostly a matter of taste and optics. I do recommend to not mix styles and be consistent within a given project.

Current convention

Our current BEM naming convention looks...

Vortrag: Content Security Policy: Eine Einführung

Grundidee

CSP hat zum Ziel einen Browser-seitigen Mechanismus zu schaffen um einige Angriffe auf Webseiten zu verhindern, hauptsächlich XSS-Angriffe.

Einschub: Was ist XSS?

XSS = Cross Site Scripting. Passiert wenn ein User ungefiltertes HTML in die Webseite einfügen kann.

<div class="comment">
  Danke für den interessanten Beitrag! <script>alert('you have been hacked')</script>
</div>

Rails löst das Problem weitgehend, aber

  • Programmierfehler weiter möglich
  • manchmal Sicherheitslücken in Gems oder Rails

Lösungsid...

Nokogiri: CSS syntax for XML namespaces

<soapenv:Envelope>
  <soapenv:Body>
    <elem>
      <nest>...</nest>
    </elem> 
  </soapenv:Body>
</soapenv:Envelope>

CSS selectors are a very simple tool to select elements from a Nokogiri document. However, the colon in the XML namespace syntax does not work with CSS. When selecting namespaced elements, you need to replace their colon (soapenv:Envelope) with a pipe (soapenv|Envelope):

document = Nokogiri::XML(xml)
nest = document.at_css 'soapenv|Envelope soapenv|Body elem nest'
Repeats

HTML: Making browsers wrap long words

By default, browsers will not wrap text at syllable boundaries. Text is wrapped at word boundaries only.

This card explains some options to make browsers wrap inside a long word like "Donaudampfschifffahrt".

Option 1: Soft hyphens

Unicode has a soft hyphen character you can use to mark optional word division opportunities. The soft hyphen is an invisible character with zero width. Only when the browser decides to wrap at a soft hyphen, it is turned in...

This website uses short-lived cookies to improve usability.
Accept or learn more