Multiple elements with same css but different breakpoints

The application I’m working on has a number of pages that display a full-page table. I used Filament Groups’ stack only option from tablesaw and have it looking and working pretty nice.

Then came the tricky bit. Each of these tables has a different number of columns; one might have 4 and another might have 12. So I need a different breakpoint for each table.

It seems surprising that it’s only now, after all the time I’ve been using media queries, that I have stumbled into a problem like this. So what choices are there here?

I could repeat the whole of the CSS for each variation of the table and simply change the value of the media queries for each variation to be unique. But the CSS isn’t small, so that’s a lot of repetition and will be a real pain when it comes to making a simple style change and having to repeat it for every variation of the table. I want to make this as DRY as possible.

Following a few hours of staring at the code in some kind of stunned confusion at how simple but unsolvable this problem seemed, and after my usual Stack Overflow fail, here’s the solution I ended up with.

Firstly, I refactored my sass so that all the wide screen styles were chunked into one min-width media query (so the mobile-first default stylesheet had no media queries at all). I appended a class to the wrapper that would be unique to each variation of the table, starting here with .index-table--default.

// Table page media queries
.index-table.index-table--default

  // Breakpoint for tablesaw
  .index-table__content
    +tablesaw-stack(em(600))

  // Breakpoint for table styles
  @media screen and (min-width: em(600))
    content...

If I stopped at this point, I would need to repeat this for each variation. To avoid that, and to keep the table names and breakpoints in one tidy and configurable place, I created a sass map for each variation of the table:

$table-breakpoints: (default: em(600), invoices: em(500), payments: em(760), etc...)

With the breakpoints now defined, I used the @each directive to loop through each of the keys in the map:

@each $table, $breakpoint in $table-breakpoints

This assigns the variable $table to the key and $breakpoint to the associated value in the map.

The $table key is used to define the table class name:

// Table page media queries
.index-table.index-table--#{$table}

The $breakpoint variable associated with the key is used in the media queries:

// Breakpoint for tablesaw
.index-table__content
  +tablesaw-stack(#{$breakpoint})

// Breakpoint for table styles
@media screen and (min-width: #{$breakpoint})
  content...

So the final code looks something like this:

$table-breakpoints: (default: em(600), invoices: em(500), payments: em(760), etc...)

@each $table, $breakpoint in $table-breakpoints

  // Table page media queries
  .index-table.index-table--#{$table}

    // Breakpoint for tablesaw
    .index-table__content
      +tablesaw-stack(#{$breakpoint})

    // Breakpoint for table styles
    @media screen and (min-width: #{$breakpoint})
      content...

As I said, this loops through for each key in the map, so the output CSS is not dry at all, but I don’t think there’s a way to avoid that. In development at least, this should be a lot easier to maintain. Adding a new breakpoint is as simple as adding the new table name as a key in the map and assigning the breakpoint as a value – that’s it. Any changes to the style also only need to be made in the one place too, since I’m using the @each loop to output the variations.

It’s the first time I’ve used sass maps and I think it looks like they might be pretty useful. And loops, which at first blew my mind a little, are beginning to make more sense each time I wrestle with them.

Linotype: The Film

Last night, Marie and I saw this documentary film about the Linotype type casting machine and had that feeling again that we were born in the wrong decade. It’s inspiring to hear these old guys talking so lovingly about the machine they sat at for most of their working lives. In the future, I wonder if we’ll have the same fondness in retrospect for the design tools and devices we use now?

Made me nostalgic for printmaking back at Hot Bed Press when I used to live in the North.

Gathering

Now this gathering of general materials is important because this is where the previously stated principle comes in — namely, that an idea is nothing more nor less than a new combination of elements. In advertising an idea results from a new combination of specific knowledge about products and people with general knowledge about life and events.

James Webb Young – A Technique For Producing Ideas

Absolute centring a dialog with lots of content

I’ve been wrestling with centring a dialog over a page today. This seems to be a good go-to solution and it got me a long way towards where I want to be. The problem I found though was that if there is plenty of content in the dialog or if it expands to reveal more, the negative top positions the dialog off the top of the window.

I couldn’t think of a CSS solution to this, so here’s the js solution I came up with with a bit of refactoring from Joel.

centreTheDialog: ->

   if (Modernizr.mq('(min-width: 37.5em)'))
      $dialog = $('[data-js-dialog]')
      $minTop = 50
      $left = ($(window).width() / 2) - ($dialog.width() / 2)
      $top = ($(window).height() / 2) - ($dialog.height() / 2)

      if ($top < $minTop)
        $top = $minTop

      $dialog.css({'top': $top; 'left': $left})

    else
      $dialog.removeAttr 'style'

Using jQuery for a full document height overlay on mobile and tablet

My wife is learning front-end development at the moment and she sometimes tells me how frustratingly difficult it can be to figure out how to move a single element here or there on a page. I try to be supportive and tell her that it gets easier, but then even now I have days where just moving something on a page almost completely confounds me and I feel like I’m back at the beginning again. Today was one of those days: I spent the best part of it going through every possible technique for an modal overlay background like the light-box effect.

It sounds like it should be easy. Position fixed, top left 0 and width height 100%. And that works on desktop, but when I test it on iPhone and iPad, the fixed position overlay background is glitchy as it doesn’t repaint until you finish scrolling. (And yep, I’ve followed all the stuff about avoiding using overlays if at all possible. But sometimes they really are necessary.) There’s a technique outlined on Codrops using position absolute, but no matter what I tried, if the dialog grew to be bigger than the initial height of the document, the page would extend but the overlay background would not, leaving a gap at the bottom.

I tried all the techniques on the Codrops article and the iPad rejected them all. The mega-outline and mega-box-shadow techniques pretty much crashed the browser completely. (I should note: I don’t mean to be critical the Codrops article, it’s brilliant and the site is an awesome resource that I use very regularly. I mean to be critical of the iPad.)

I didn’t want to resort to javascript, but in the end I decided I had to. I stumbled into this answer on Stack Overflow and decided to use something like it. With a bit of help from the guys in the Red Guava coding chat room, here’s what I came up with:

function makeOverlayFullDocHeightOnTouchScreen() {
  $(".touch .modal-overlay").css({
    "height": $(document).height()
  });
}
if (!$("body").hasClass("no-touch")) {
  makeOverlayFullDocHeightOnTouchScreen();
  $(window).on("orientationchange", makeOverlayFullDocHeightOnTouchScreen);
}

So basically, this is going to check if it is a touch screen device to start with using the class added by Modernizr. If so, it’s going to measure the height of the document and add that as an inline style to the overlay element. It’s crazy to think the amount of pain that led up to and went into these few simple lines of code, but I’ll use this from now one every time I have to add an overlay to a site until mobiles and tablets can handle some basic css.

Stagger transition delay with SASS @while

I’m adding one of those subtle animation effects to the fields in a form that has just appeared. You know, the one where there’s a staggered transition delay so the form fields fade in and slide up to stack under each other (like on the sign-up form here).

I figured it would be useful to create something that I could reuse quickly elsewhere, so I had a look at the SASS control directives. I had a go at the @while statement and came up with this function:

@mixin stagger-transition-delay($i, $initial-delay, $stagger-delay) {
  @while $i > 0 {
    &:nth-of-type(#{$i}) {
      @include transition-delay($initial-delay + $stagger-delay * $i)
    }
    $i: $i - 1;
  }
}

Which you can then use like so:

.my-class {
  opacity: 0;
  @include transform(translateY(rem(50)));
  @include stagger-transition-delay(7, 0.5s, 0.1s);
}

The transition-delay and transform are Bourbon mixins.

The $initial-delay is useful if you want to delay the start without effecting the stagger time. In my example, I need to wait for the form itself to finish animating in before starting the stagger animation.

Here’s a very rough working example.

Using Vimeo for HTML5 video flash fallback

Here’s the code for the video player I’m working on:

<video preload="none" id="video--online-bookings" poster="/assets/online-bookings-tour-poster.png" controls>
  <source src="/assets/online-bookings-tour.webm" type="video/webm">
  <source src="/assets/online-bookings-tour.mp4" type="video/mp4">
  <track src="/assets/online-bookings-tour-subtitles-en.vtt" label="English subtitles" kind="subtitles" srclang="en"></track>
</video>

Looking for a way to provide a fallback for browsers that don’t support html5 video, I found this. I like the simplicity of being able to drop an object on the page and tell it to use a video hosted on Youtube (I’ve spent waaaaay too long in Adobe Media Encoder. It doesn’t output swf files, so I really don’t want to have to go through the bother of finding out how to do that).

We use Vimeo, not Youtube, and it took a while to find the right embed code. But it’s there if you dig for it: click on the share button on the video, click ‘show options’ to expand the dialog, then down at the bottom there’s a half-transparent link that says ‘use old embed code’. Click that and copy code from the textarea above.

Our video player now looks something like this:

<video preload="none" id="video--online-bookings" poster="/assets/online-bookings-tour-poster.png" controls>
  <source src="/assets/online-bookings-tour.webm" type="video/webm">
  <source src="/assets/online-bookings-tour.mp4" type="video/mp4">
  <object width="100%" height="100%" type="application/x-shockwave-flash" data="http://vimeo.com/moogaloop.swf?clip_id=91383150&amp;force_embed=1&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=1&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0">
    <param name="wmode" value="transparent" />
    <param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=91383150&amp;force_embed=1&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=1&amp;color=00adef&amp;fullscreen=1&amp;autoplay=0&amp;loop=0" />
  </object>
  <track src="/assets/online-bookings-tour-subtitles-en.vtt" label="English subtitles" kind="subtitles" srclang="en"></track>
</video>

The fallback shouldn’t be loaded unless the browser can’t play the webm or mp4 files. The <param name="wmode" value="transparent" /> stops the flash player from being on top of everything in the z-index.

Detecting when ‘done’ is pressed on iPhone HTML5 video

I have a html5 video in a modal overlay with custom controls. The iPhone ignores all of that and jumps into full screen mode to play the video. The problem is that when I click ‘done’, the full screen video is dismissed, but the overlay remains and the video is there with the custom controls which are unusable.

The solution is to listen for webkitendfullscreen.

// Dismiss video on iphone when press done
var video = document.querySelector("video");

video.addEventListener("webkitendfullscreen", function() {
  dismissModalAndResetVideo();
}, true);

There’s a webkitbeginfullscreen too, should you need it.

Freelancers tax records template for Numbers

It’s that time of year again… Historically I’ve been really bad at keeping on top of my records for tax and have, until recently, submitted my self assessment a day or two before the deadline. Luckily, my accounts have got a lot easier than they used to be as I now only really have the one regular monthly payment, with a few other bits on the side sometimes. Last year I managed to turn it around and submitted the form by the end of April. This year, I was trying to log in to the HMRC website only to realise I was trying to submit before the tax year had even ended!

Read more…

New Logo for Cliniko

First attempts

Back in December 2012 when I was applying for the job as designer at Red Guava, I asked Joel if he would be open to allowing me to redesign the Cliniko logo. He replied, “I never rule out anything but we have done a lot of branding work already and have got some great recognition for our logo. There would need to be business sense in doing so.” I took that as a yes and didn’t look back.

Read more…