Posts

I’ve been become more comfortable playing with CSS features that are beyond just making sure that typography works well in all form factors.

Rotate On Hover

One of the things that I like is the subtle and fun rotation that Smashing Magazine does with the author’s photo when you first visit an article and how it moves to a fully vertical position when you hover over the image. I’ve always thought that that’s backward and that it should move to the diagonal position when you hover over the image… so let’s try to do it that way.

The default state for the image sets the dimensions and a border (I like borders on images).

img {
border: 5px solid rebeccapurple;
height: 150px;
width: 150px;
}

The change happens in the hover state. Here we do two things:

We tell the browser that we want the rotation to happen from the bottom left corner

We use rotate to move the image -15 degrees (15 degrees counterclockwise)

The basics work but there’s one more thing that I want to do. Transform allows us to chain effects so why not make the image slightly bigger as we rotate it? The modified code adds a scale transform to the existing rotation.

As I was working on my last post about paged media I discovered one thing we can do to make footnotes for the web a little more user-friendly. Paged Media has a way to hide the text of the footnote from being displayed on the page… wouldn’t it be nice to do that with web content as well without having to change the document we’re working with?

CSS on its own will take you part of the way there… so let’s explore how can Javascript help. What we want to accomplish:

Hide all the elements with class footnotes

Add a number corresponding to the number of the footnote

If possible make it a hyperlink

Create an ordered list

Create a link for each footnote pointing to the footnote number

First, we define the code we’ll use to generate the footnotes. By using a span with an associated class

<span class='footnote'>Another footnote</span>

On the Javascript side, we capture all the footnotes using querySelectorAll to get a list of all the elements that match the .footnote selector.

Even though the querySelectorAll returns a nodeList, not an array. While we can still use the forEach method, it has none of the other array methods. If we need other array methods we can covert the list into an array using destructuring assignments or array.form to create an array you can operate on. To be on the safe side, I used destructuring to convert the list into an array.

Now that we have the array, the first step is to generate the footnote marker and link. We use (i+1) instead of just i because arrays start at 0 instead of 1.

Once we have the footnote marker we insert it into the document adjacent to the footnote text; only then we can remove the footnote text from the document, otherwise, we would have nowhere to insert the marker.

One thing that the web is sorely lacking is the ability to create print-ready content from our web pages. CSS provides specifications for paged media but the support in browsers leaves a lot to be desired, forcing people into tools that accomplish the goals of creating high-quality print content.

In many instances, I will cut pieces of the code where they are not relevant. You can find the full stylesheet along with the resulting PDF from the Github Repo

One thing we need to remember is that for this particular project we’re doing everything in the command line so download speed is not as big a concern as if we were doing this online at the same time as trying to serve our regular content.

Getting started

The first thing we do is to load the fonts using a simplified @font-face syntax. Rather than loading all the font formats as we would for a regular web page, we only load WOFF (compressed with Zopfli) to make our lives easier.

No, we cannot use Variable Fonts with Paged Media Processors.

In the next step, we’ll define some global parameters that will apply to all content.

We use the html element to define the global font for the document.

The h1 element is interesting. We capture the content of the element (the value) to use later as the running header for our different types of content.

Next, we define the global page for the document. This is what all the other pages will inherit from so we save ourselves from having to retype blocks of CSS over and over.

We define the size of the printed page to be American Letter (8.5 by 11 inches) with a 1-inch margin all around.

The margin attribute takes one to four values and follows the same rules as regular CSS:

When one value is specified, it applies the same margin to all four sides

When one value is specified, it applies the same margin to all four sides

When two values are specified, the first margin applies to the top and bottom, the second to the left and right

When three values are specified, the first margin applies to the top, the second to the left and right, the third to the bottom

When four values are specified, the margins apply to the top, right, bottom, and left in that order (clockwise)

Next, we set what we want to put in the top right corner of the document. We indicate that we want to pull the doctitle string from h1 element for the corresponding section and that we want it to be 9 points (where 1pt equals 1/72 of an inch)

Finally, we set footnote attributes that we want to carry throughout the document.

Chapters and Appendices require some extra work. Because we usually have more than one chapter and can have multiple appendices, we are using counters and we want to indent all paragraphs after the first one we take some extra work to make sure it works correctly.

For all h1 elements inside chapter sections we want to do three things:

Capture the text of the element

Reset the figure counter

Reset the table counter

Using the :before pseudo-element we add a string containing the word Chapter and the current value of the chapter counter.

Sadly browser support for paged media and most of the generated content for paged media specs is severely lacking, even in browsers that support reading ebooks in the browser (Edge). So we have to work around these deficits by being creative in how we format our content to print from the web.