Building web applications: Beyond the happy path
When building a web application, one is tempted to claim it "done" too early. Make sure you check this list.
Different screen sizes and browsers
Desktops, tablets and mobile devices have all different screen resolutions. Does your design work on each of them?
- Choose which browsers to support. Make sure the page looks OK, is usable and working in these browsers.
- Use @media queries to build a responsive design
- If you do not suppo...
How to force horizontal panel layout for Chrome
Chrome's developer tools automagically choose vertical or horizontal panel layout, based on their width. You can disable that magic.
In the developer tools, klick the cogwheel icon (or press F1
when focusing the dev tools) to open the settings overlay.
Under "Preferences", in the "Appearance" section, find the "Panel layout" option. Set it to your liking.
Alternatively, press Ctrl+Shift+P and search for "panel layout".
Wat?
Vertical means that the DOM tree is next to the styles/etc panel, like so:
. - Use the
html
tag to define a basefont-size
so you can use [rem
units](https://www.sitepoint.com/underst...
You can implement basic object-fit behavior with background images
So you want to use object-fit
, but you also need to support Internet Explorer.
One option is to use lazysizes as a kinda-polyfill. Another option is to implement the requirement with background-size: contain
, and background-size: cover
, which is supported in IE9+.
E.g. to make an image cover a 100x100 px² area, cropping the image when nece...
object-fit polyfill by lazysizes
All new browsers support the new object-fit
CSS property. It allows to specify how an element behaves within its parent element and is intended for images and videos. The most useful values are contain
(fit-in) and cover
(crop).
Unfortunately, IE does not support this yet. However, if you're already using lazysizes, you can use its object-fit polyfill!
Usage
In your Javascript manifest, require them like this:
#= require plugins/object-fit/ls.obj...
Dynamically uploading files to Rails with jQuery File Upload
Say we want …
- to create a
Gallery
that has a name andhas_many :images
, which in turn have a caption - to offer the user a single form to create a gallery with any number of images
- immediate uploads with a progress bar per image
- a snappy UI
Enter jQuery File Upload. It's a mature library that can do the job frontend-wise. On the server, we'll use Carrierwave, because it's capable of caching images.
(FYI, [here's how to do the u...
UI Sortable on table rows with dynamic height
UI sortable helps reordering items with drag 'n drop. It works quite fine.
Proven configuration for sorting table rows
When invoking the plugin, you may pass several options. This set is working fine with table rows:
$tbody.sortable # Invoke on TBODY when ordering tables
axis: 'y' # Restrict drag direction to "vertically"
cancel: 'tr:first-child:last-child, input' # Disable sorting a single tr to prevent jumpy table headers
containment: 'parent' # Only drag within this container
placehol...
Preloading images with CSS
Sometimes you want to preload images that you will be using later. E.g. if hovering over a an area changes its background image, the new image should be preloaded. If you only load it once the user starts hovering, there will be a delay until the background image flips.
The attached article explains how to preload images with only CSS. No Javascript required.
The gist is:
.element:after {
content: url(img01.jpg) url(img02.jpg) url(img03.jpg);
display: none;
}
How to inspect RSS feeds with Spreewald, XPath, and Selenium
Spreewald gives you the <step> within <selector>
meta step that will constrain page inspection to a given scope.
Unfortunately, this does not work with RSS feeds, as they're XML documents and not valid when viewed from Capybara's internal browser (e.g. a <link>
tag cannot have content in HTML).
Inspecting XML
If you're inspecting XML that is invalid in HTML, you need to inspect the page source instead of the DOM. You may use Spreewald's "... in the HTML" meta step, or add this proxy step fo...
How to explain SQL statements via ActiveRecord
ActiveRecord offers an explain
method similar to using EXPLAIN
SQL statements on the database.
However, this approach will explain all queries for the given scope which may include joins
or includes
.
Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:
User.where(id: 1).includes(:articles).explain
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
+----+-------------+-------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-----...
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 inside their container. 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...
How to reverse the order of HTML elements with CSS
Imagine you have a list you want to render inline on large screens, but stacked on small screens.
<ul>
<li>high</li>
<li>medium</li>
<li>low</li>
</ul>
ul { white-space: nowrap } /* optional: keep items in one line no matter the available width */
li { display: inline-block }
@media (max-width: 600px) {
li { display: block }
}
Now imagine you want the rightmost item to be the topmost item on small screens. You'll need to invert the order of list items, but only for large screens. Here are some approaches to do so:...
Centering with CSS vertically and horizontally (all options overview)
There are a million ways to center <div>
s or text in CSS, horizontally or vertically. All the ways are unsatisfying in their own unique way, or have restrictions regarding browser support, element sizes, etc.
Here are two great resources for finding the best way of aligning something given your use case and browser support requirements:
- How to center in CSS
-
A long form that lets you define your use case and browser support requirements, then shows you the preferred way of aligning.
[Centering CSS: A co...
Showing a custom maintenance page while deploying
Note
The maintenance mode is enabled on all application server as soon as the file
/public/system/maintenance.html
is present.
Installation
Add this line to your application's Gemfile:
gem 'capistrano', '~> 3.0'
gem 'capistrano-maintenance', '~> 1.0'
Add this line to you application's Capfile:
require 'capistrano/maintenance'
Enable task
Present a maintenance page to visitors. Disables your application's web interface by writing a #{maintenance_basename}.html
file to each web server. The servers m...
AllThingsSmitty/css-protips
A list of surprisingly clever CSS expressions for common use cases.
How to open a new tab with Selenium
Until recently, you could open a new tab via window.open
when using execute_script
in Selenium tests. It no longer works in Chrome (will show a "popup blocked" notification).
This is because browsers usually block window.open
unless the user interacted with an element for security reasons. I am not sure why it did work via Selenium before.
Here is an approach that will insert a link into the page, and have Selenium click it:
path = "/your/path/here"
id = "helper_#{SecureRandom.hex(8)}"
execute_script <<-JAVASCRIPT
...
CSS: Select elements that contain another selector
CSS4 comes with :has
. E.g. h1:has(b)
would select all <h1>
tags that contain a <b>
tag.
This is implemented in no browser but the jQuery query engine already supports it as a custom extension.
Spreewald: Click on an element with a CSS selector
Spreewald 1.4.0 comes with this step:
When I click on the element ".sidebar"
We recommend to define a selector_for
method in features/support/selectors.rb
so you can refer to the selector in plain English:
When I click on the element for the sidebar
Spreewald: Check that a CSS selector is present on the current page
Spreewald 1.3.0 comes with these steps:
Then I should see an element ".panel"
Then I should not see an element ".sidebar"
Then I should see an element ".twitter-timeline"
We recommend to define a selector_for
method in features/support/selectors.rb
so you can refer to the selector in plain English:
Then I should see an element for a panel
Then I should not see an element for the sidebar
Then I should see an element for the Twitter timeline
CSS Fontstack: An overview of web/web safe font support
Web safe fonts are fonts that are pre-installed by many operating systems. While not all systems have the same fonts installed, you can use a web safe font stack to choose several fonts that look similar, and are installed on the various systems that you want to support. If you want to use fonts other than ones pre-installed, as of CSS3, you can use Web Fonts.
If you need to install any of the widely-supported fonts listed there, you'll probably find them at www.fontpalace.com.
Case Study: Analyzing Web Font Performance
Table of contents of the linked article:
What are Web Fonts?
- Advantages of Web Fonts
- Disadvantages of Web Fonts
- Fallback Fonts
- CSS3 @font Declaration Example
- Fallback Font Example
- Render Blocking and Critical Rendering Path
- FOIT
Optimizing Web Font Delivery Further
- Prioritize Based On Browser Support
- Choose Only Styles You Need
- Character Sets
- Host Fonts Locally or Prefetch
- Store in LocalStorage with Base64 Encoding
- Another Method
Web Font Pe...
Lazy-loading images
Note
This card does not reflect the current state of lazy loading technologies. The native lazy attribute could be used, which is supported by all major browsers since 2022.
Since images are magnitudes larger in file size than text (HTML, CSS, Javascript) is, loading the images of a large web page takes a significant amount of the total load time. When your internet connection is good, this is usually not an issue. However, users with limited bandwidth (i.e. on mobile) need to mine their data budget...
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
...
Know what makes your browser pant
I figure we needed a definitive reference for what work is triggered by changing various CSS properties. It's something I get asked about often enough by developers, and while we can do tests with DevTools, I have both the time and inclination to shortcut that for everyone. I'm nice like that. —Paul Lewis