How to fix HTML elements being cut off when printing

When you print (or print preview) and elements are cut off (e.g. after 1st page, or "randomly") you should check your CSS rules for these:

  • Is there an element with "display: inline-block" that surrounds your content? Make sure it has "display: block" for printing.
    This primarily affects Firefox and Internet Explorer. Chrome seems to be able to handle inline-block elements in most cases.

  • Does the element itself, or a container, define "overflow: hidden"? Use "overflow: auto" (or maybe "overflow: visible") instead.

  • Is th...

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: hyphens CSS property

Modern browsers are able to hyphenate natively with the CSS property hyphens:

hyphens: auto

There is also hyphens: none (disable hyphenations even at ­ entities) and hyphens: manual (hyphenation at ­ only).
This feature was integrated [just ...

Fixing flaky E2E tests

An end-to-end test (E2E test) is a script that remote-controls a web browser with tools like Selenium WebDriver. This card shows basic techniques for fixing a flaky E2E test suite that sometimes passes and sometimes fails.

Although many examples in this card use Ruby, Cucumber and Selenium, the techniques are applicable to all languages and testing tools.

Why tests are flaky

Your tests probably look like this:

When I click on A
And I click on B
And I click on C
Then I should see effects of C

A test like this works fine...

Async control flow in JavaScript: Promises, Microtasks, async/await

Slides for Henning's talk on Sep 21st 2017.


Understanding sync vs. async control flow

Talking to synchronous (or "blocking") API

print('script start')
html = get('/foo')
print(html)
print('script end')

Script outputs 'script start', (long delay), '<html>...</html>', 'script end'.

Talking to asynchronous (or "evented") API

print('script start')
get('foo', done: function(html) {
  print(html)
})
print('script end')

Script outputs 'script start', `'...

How to fix broken font collisions in wkhtmltopdf

If you are using PDFKit / wkhtmltopdf, you might as well want to use custom fonts in your stylesheets. Usually this should not be a problem, but at times they include misleading Meta-information that leads to a strange error in the PDF.

The setup

  • The designer gave you two fonts named something like BrandonText-Regular and BrandonText-Bold. (With flawed Meta-information)
  • You have a HTML string to be rendered by PDFKit
  • For demonstration purposes, this strin...

Deleting stale Paperclip attachment styles from the server

Sometimes you add Paperclip image styles, sometimes you remove some. In order to only keep the files you actually need, you should remove stale Paperclip styles from your server.

This script has been used in production successfully. Use at your own risk.

# Config #######################################################################
delete_styles = [:gallery, :thumbnail, :whatever]
scope = YourModel # A scope on the class with #has_attached_file
attachment_name = :image # First argument of #has_attached_file
noop ...

Cucumber: Test that an element is not overshadowed by another element

I needed to make sure that an element is visible and not overshadowed by an element that has a higher z-index (like a modal overlay).

Here is the step I wanted:

Then the very important notice should not be overshadowed by another element

This is the step definition:

Then(/^(.*?) should not be overshadowed by another element$/) do |locator|
  selector = selector_for(locator)
  expect(page).to have_css(selector)
  js = <<-JS
    var selector = #{selector.to_json};
    var elementFromSelector = document.querySelector(selector)...

How to define height of a div as percentage of its variable width

This is useful if, for example, you want to use a background-image that has to scale with the width and the div should only have the height of the picture.

html:

<div class="outer">
  <div class="inner">
  </div>
</div>

css:

.outer {
  width: 100%;
  background-image: image-url('background.png');
  background-size: cover;
}
  
.inner {
  padding-top: 60%;
}

How does it work?

There are several CSS attributes that can handle values as percentage. But they use different other attributes as "reference value...

CSS: Don't target multiple vendor-prefixed pseudo-elements in a single rule

Some pseudo-elements need to be addressed with vendor prefixes. E.g. ::selection is not supported by Firefox, you need to use ::-moz-selection instead.

What you cannot do is to define a single CSS rule to address both the standard and vendor-prefixed form:

::selection, ::-moz-selection {
  background-color: red;
}

This rule will be ignored by all browsers. The reason is that if a browser doe...

SASS: Defining linear sizes

Just dumping this in case somebody might need it.

When you need a CSS value (a padding, margin, height etc) to shrink/grow proportionally with the parent element, you normally use percentage values. However, if you need specific values at two given widths, you need to turn to linear functions. The mixin below gives you just that.

// Call with two desired values at two different widths.
// Returns a calc() expression that will scale proportionally between those two.
// Example:
//   Spaci...

Sass: Don't put CSS rules into partials that you import multiple times

TLDR: When you put CSS rules into a partial and import that partial multiple times, the CSS rules will be duplicated in the compiled CSS.


Here is a Sass partial called _fonts.sass that contains both CSS rules and a mixin:

@font-face
  font-family: SuperType
  src: url('supertype.woff')
  
=title-font
  font-family: SuperType

This _fonts.sass is not practical in CSS projects that are organized over multiple files: When you...

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...

Styling SVGs with CSS only works in certain conditions

SVG is an acronym for "scalable vector graphics". SVGs should be used whenever an image can be described with vector instructions like "draw a line there" or "fill that space" (they're not suited for photographs and the like). Benefits are the MUCH smaller file size and the crisp and sharp rendering at any scale.

It's a simple, old concept brought to the web – half-heartedly. While actually all browsers pretend to support SVG, some barely complex use cases get you beyond common browser support.

In the bas...