I love writing CSS. One of the best things I know is getting a new design and spend time implementing it. But I rarely get to do that anymore.

It’s a blessing as well as a curse that CSS has such a low threshhold for getting started. The relative simpleness of CSS and HTML means that the world of web development opens up in a way that JavaScript can not offer, other languages even more so. But it also means that it’s easy to miss that CSS can be hard, and that you need to study and pratice to understand how and why things work.

As soon as you try more complex things you run into obstacles. Floating and negative margins are often used to fix things. Developers get angry, saying that CSS is a crappy way to do things, and it might well not be the optimal way. But still, I think that some of the problems lies in the fact that since it seems so easy at first glance, many don’t bother learning it for real.

Writing good, reusable CSS is not easy, and writing a 3000 lines long CSS file can happen without anyone noticing. JavaScript often gets blamed for making it easy to write bad code, but with CSS this is even more true. It so easily happens that you pile new rules on top of old, the cascading part of CSS that is so great gets overused.

But I have noticed in the last few month or year that the amount of CSS that I’m writing has decreased enormously. Great, and sad, I say. Great beacuse you have some sort of base to build upon and use complete components from. Before you hade to write it all yourself, but with the advent of frameworks, internal as well as external, comes using already written stuff. Many times this is great, you have some sort of baseline and don’t have to reinvent the wheel over and over again.

But still, I miss it.

TLDR: Can’t be done with ng-click, use jQuery or jQLite, or don’t do it at all

Say that you have a web page that have a search bar at the top, but the search input is hidden from view when viewed from a small device. You have a button with a looking glass that when tapped it shows the input field. When the user want to search they don’t want to first tap the button and then tap again to focus on the input field to have the keyboard appear, they expect this to happen at once. So one element is tapped, but another should get focused.

This is quite easily done in most browsers, but not those running on iOS. The iOS developers, preferring a stable and simple UI with little visual jank, where the keyboard does not show up unnecessarily, have ensured that input elements can’t be focused without the user initiating the process.

When does the keyboard appear in iOS?

First thing first, what are the ways the keyboard appears in iOS?

  1. The natural way, the user taps an input element and the browser focuses that element and shows the keyboard
  2. The programatic way, the user taps an element and a click handler sets the focus to a different element, but within what the iOS browser considers to be the same action.

Focus using a click handler

You can attach a jQuery click handler (probably also a native click handler, but I didn’t try that) to an element and inside that set focus on an input field, and that will show the keyboard, like this:

1
2
3
$('.wrapper').on('click', '#some-button', function () {
    $('#some-input').focus();
});

This will work in iOS and all other browsers that I’ve tried, since even iOS considers it user initiated. But if you remove the focus part from the timeline, for example putting it inside a timeout, it will no longer work in iOS, but other will happily set focus.

So this will not work:

1
2
3
4
5
$('.wrapper').on('click', '#some-button', function () {
    setTimeout(function () {
        $('#some-input').focus();
    });
});

The call to focus has to be directly inside the click handler

But what about Angular?

This is where I had trouble. The application I’m writing on at work is all Angular, and you don’t want to mix if you can help it. Mixing regular click handlers with ng-click makes for a hard to maintain application. I tried putting the exact same call to focus (using jQLite or jQuery, which ever) inside an ng-click, like this:

Template:

1
<button id="some-button" ng-click="focusOnInput()">Click me</button>

In controller

1
2
3
$scope.focusOnInput = function () {
    $('#some-input').focus();
};

But iOs couldn’t have cared less. It would not work. I have no idea why, but for some reason iOS consideres this less user initiated, perhaps Angular itself does a timeout or something like it. In the end I had to abandon ng-click in this case, even though it hurt somewhat, and use the same approach as above.

Looking around online I found others struggling with this. Some had ways around, some not, but this is all I could get to work.

This is how I implemented the user story that a user wants to change his or her profile picture by uploading a new one and choosing which part of it to show by cropping it.

I needed IE9 support, which made it all a lot harder. The end result is not very complex, code wise, but it took a long time, for me at least, to come up with the best way to go about this, and fit all the pieces together. I’m using two jQuery plugins, Jcrop for cropping and jQuery File Upload for uploading.

Note that there are some requirements on the server side. The actual cropping is done at the backend, not on the client, and of course you need a server that can store your images. You also need to have CORS set up on your server (?).

Here’s the workflow that I came up with:

  1. The user loads the page and all the elements are loaded.
  2. The user clicks ‘browse computer’ (what is this? clarify it is input field) to find a suitable image to upload.
  3. When user has selected an image, it is sent with a POST request to the server, which stores it in a temporary location.
  4. The new temporary image is loaded back onto the page and the cropping plugin is activated (image source is set to the temporary location).
  5. The user chooses which part of the image he or she wants by dragging the cropping rectangle.
  6. Once satisfied, the user saves the image, and the coordinates are sent to the server with a POST request. The image is not sent again, only the coordinates are needed.
  7. The server takes the temporary image and crops it with the coordinates and moves the cropped version to the final location.
  8. The finished image can be loaded back onto the page from the final location (for example user/image).

Why do we need to make such a fuss?

This workflow may seem longer and more complex than should be required. The main problem here is IE and especially IE9 (no surprise there). The server I was using was located on a different domain from the site, so I also had some CORS issues to contend with. The largest problem I had was when I was trying to crop the image before sending it, using Canvas (what is this?). This will not work. You need to set the image source for a canvas and IE9 or IE10 does not support, at all, the source of the canvas image to be different than the site (this includes files chosen using a file input, as their origin is null). So if you try to load the image from the computer, it will not work. And it will also not work with my separate domains setup. This can’t be fixed with CORS in IE9-10 (citation required). So let go of the canvas idea.

This means uploading the image first and then cropping it. This is where you might want to try and make your own FormData object and set image, with base64. This, also, is not supported by IE9. There is no way to create your own xhr request and POST an image with it. What is needed is a form tag that does the actual posting.

I was working here with a SharePoint site, and those are wrapped in one gigant form tag, and you can’t have nestled form tags. So I needed an iFrame with the form tag in it. Here’s where jQuery File Upload is your savior. Though the documentation is somewhat lacking, once you get it to work it actually works, and you don’t have to implement the actual file upload youself, which is a really good thing.

On to the actual implementation.

Implementing the file upload

First step is to include all the necessary files for the plugins to your page, of course. From Jcrop I just included the jquery.jcrop.min.js. In jQuery File Uplpoad, which is a bit more complex, I ended up needing the files jquery.fileupload.js, jquery.fileupload-image.js, jquery.fileupload-process.js, jquery.fileupload-validate.js and jquery.iframe-transport.js, but this could differ for your needs. Read the documentation carefully and try not to rip out your hair in the process (it is quite a challenging read, the information is all over the place). I also needed to deploy a file called result.html found in the project. This is to make it work in IE9, more on that below.

I added this markup:

<input id="fileupload" type="file" name="files[]">

And to my JavaScript file I added this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$('#fileupload').fileupload({
    forceIframeTransport: true,
    url: == url to your server ==,
    // The regular expression for allowed file types, matches
    // against either file type or file name:
    acceptFileTypes: /(\.|\/)(jpe?g|png)$/i,
    success: function (e, data) {
        $uploadPanel.hide();
        showCroppingPanel();
    },
    fail: function (e, data) {
        console.log(e);
        console.log(data);
    },
    done: function (e, data) {
        console.log(data);
    }
    }).on('fileuploadprocessalways', function (e, data) {
        var currentFile = data.files[data.index];
        if (data.files.error && currentFile.error) {
          // there was an error, do something about it
            console.log(currentFile.error);
            $wrongFileMessage.show();
        }
    });

    // This reditect the POST to a html file
    // needed for the iframe, and perhaps for the CORS support
    $('#fileupload').fileupload('option',
        'redirect',
        '/result.html?%s'
    );

Let’s go through it step by step.

.fileupload initializes and after that you give it options. The forceIframeTransport forces it to always create an iframe to make the POST request to. This is needed for IE9, which does not support the sending of images via xhr.

url should be self explanatory, it’s the location of your server, to where the POST request will be made.

acceptFileTypes takes a regular expression to match the file ending. And this is where I found a bit of a gotcha. You can only catch this “error” (when a user uploads the wrong file type) if you also implement the fileuploadprocessalways bit of the code above. This “pauses” the upload if there is an error, and you can for example show an error message to the user, which is what I did.

The last part is also for the iFrame. It redirects the POST to an iFrame and the HTML file is needed there. Don’t forget the %s at the end there, it won’t work without it.

Once you get all this to work, the image should magically be sent to the server. One big problem for me at first was the success handler not running, even though the image was successfully uploaded and the server returned 200. This was because I, according to the startup guide, had specified that the result should be in JSON, but the server was not sending JSON.

My main problem now is that the error handler is not run even though the server returns an error. Don’t yet know why this is.

Implementing the cropping

At this point you hopefully have a temporary image on the server. Create an <image> tag on your page, and in the success handler of the previous part, add the newly uploaded image url as source. I did it like this:

1
$croppingImage.attr('src', "http://myserver/user/picture-temp");

And then wait for it to load, and activate the Jcrop plugin on it:

1
2
3
4
5
6
7
8
9
10
11
$croppingImage.load(function () {
    $croppingImage.Jcrop({
       setSelect: [96, 96, 0, 0],
       minSize: [minSize, minSize],
       aspectRatio: 1,
       onSelect: setCoordinates
    }, function(){
       jcrop_api = this;
    });

});

As usual there are a lot of options that you can implement, I just wanted the selection to be a square.

Here I give the callback setCoordinates for each time a user updates the selection.

Those coordinates are then used when the user clicks a button.

1
2
3
4
5
6
7
8
9
10
$cropAndSaveButton.on('click', function (x1, x2, y1, y2) {
        // This happens when a user clicks to crop and save

        var requestUrl = "user/picture/crop-and-enable/" + x1 + "/" + y1 + "/" + x2 + "/" + y2;

        $.ajax({
            url: requestUrl,
            method: POST
        }).done(reloadPage);
    });

Depending on your serverside implementation here, you could send the coordinates in different ways, this is the way this backend had implemented it.

This was just an overview of how the flow and process of uploading and cropping an image could work, to help give an idea of how to think. I hope it will help someone out there.

I grew up with it and it’s hard to shake. It follows me around, looking over my shoulder everytime I try to position anything. That deeply ingrained hatred of tables. Nothing was as ugly and disgraceful as using tables to position content (that and maybe using capital letters for your tags).

  • What, are you not using THE BOX MODEL? I can’t work like this.

I sometimes sit and glare longingly at those at the office that don’t have to support the older versions of IE. Imagine the glory and wonder of using Flexbox! To be able to roll around in align-items: center, revel in justify-content and delight in flex width. But, alas. It is not so, using flexbox for corporate oriented (especially SharePoint) styling is still some years off.

But I still have to vertically align things all the time. And that’s the reason for this post. Yes, it is true. I have started to use tables to get things to where I want them. Not actual tables, but virtual ones with div and span elements with display table. And I have come to, maybe not love it, but at least rather like it. It sort of works, if used correctly. There is a learning curve, an especially steep one if your brain is telling you to RUN AWAY. But with some time and determination you too can get there.

The problem to solve

Typically we’re talking about an icon that should be centered vertically to a text of unspecified height. Position: absolute won’t help you here, nor will margin top, since the height varies. What I used to do was use a background image with background-position: center. But these days we have to take retina screens into account. Begone blurry images!

But what about svg?

says you.

Yes, that would also be nice, but legacy systems prevent me from using that (long story, SharePoint is to blame). Also I would like to utilize icon libraries like FontAwesome.

The solution

Use table layout for this! The wrapping parent gets:

1
2
display: table;
padding: 10px; // For good looks

And then every child element gets

1
2
display: table-cell;
vertical-align: middle;

And no padding or margin top or bottom on the children, that messes everything up. Both child elements now becomes as high as the highest of them, and the content is placed in the vertical middle. Magic.

Want a clearer picture and try it out yourself? Here’s a plunker where you can do that.

So you tried this and there’s no magic?

The problem with this method is that it’s mad hard to “debug”. It’s insanely difficult to understand what’s wrong when something is off in the aligning. Try to remove all set height, line-height and margins and paddings on the child elements, as well as all other positioning styling (relative or absolute).

Nothing new under the sun

Yes, people have of course used this before, but that doesn’t mean everyone has, or that it isn’t news to someone. After all, until recently I didn’t use it and I spend a fairly large amount of my day arguing with CSS.

If you came to this post because we met at the Geek Girl Meetup, I’m so, so glad to see you. My goal was to inspire at least one person to actually try this out and get started with creating webapps by using Yeoman. It would make me feel really warm inside that I actually inspired someone to get started and try it out.

If you just stumbled in here by yourself, this is a post where I list the few and wonderously simple steps to generate a webapp to use for web development using Yeoman.

The steps

Install nodejs

Go to nodejs.org to download Node. Install it on your computer.

Test Node Package manager

Open your terminal (if you’re on a Mac), or your Power Shell if you’re on a Windows. Don’t know how to do this? Don’t worry, here is a great guide for Mac, and here is a great guide for Windows. You don’t need to know more than how to open it, and think of how cool you’ll look now!

With it open, type in

1
npm

Press enter. That’s it. You get a response that says stuff about how npm works. Moving on to the next step!

Install Git

Git needs to be installed in order to get some other things (Bower) working. Go to http://git-scm.com/downloads, download and install.

Install Yeoman

Yeoman is a program that helps you generate skeletons for your future web page or web application. Install it by typing this into your terminal/Power Shell:

1
npm install -g yo

This installs Yeoman on your computer (the -g part makes sure it’s installed everwhere). If you want to know more about how Yeoman works, this is a good place to start.

Install Bower

Bower helps you out with dependencies such as jQuery or Bootstrap or something else. Install it by typing:

1
npm install -g bower

Interested in what you can do with Bower, visit this guide.

Install Grunt

Grunt is what you call a “task runner”. It does tasks for you, like minifying CSS and JavaScript, or compiling Sass, or copying files from one place to another. Let’s install it by typing:

1
npm install -g grunt-cli

If you want more about what Grunt can do for you, go this guide, which explains it nicely.

Install Webapp generator

Now we’re at the last installation step, which is to install one of Yeomans’ generators, namely Webapp. It’s a generator that creates a bunch of files and folders containing all you need for your future project. Type

1
npm install -g generator-webapp

Webapp is the most general generator from Yeoman, but there are a bunch of others.

Create project folder

Now it’s time to create a folder where your project will live. Either create it in finder/explorer, or look cool by doing it in your teminal/Power Shell:

1
mkdir my-fancy-project

Then you have to move your terminal/Poweer Shell to your new folder. This is done by the command cd which stands for ‘change directory’. Type in:

1
cd my-fancy-project

Generate your project

Now the time has come for a project to be created, finally! And all you have to do is type:

1
yo webapp

And after you pressed enter all the files and folders and content will be created, it’s almost like magic.

Start up your web application in the browser

Once it’s finished, type

1
grunt serve

This starts up the task manager Grunt, which opens your browser, with the web site on it.

Then what?

So that’s all you need to do, now you can start creating. That’s not always easy, but it’s loads more fun than writing boring HTML and creating folders and so on, which all these steps have done for you.

I made the Counting Down site by using a generator from Yeoman. You can add some JavaScript to the generated JavaScript file to create something that tells time, or just says hello, or shows flash cards from your anatomy class at school, or something entirely different.

It would make me happy if you mailed me at stinaqv@gmail.com with questions, tales or thoughts about this. I hope that you try it out and see where it takes you.

I’m starting to get slightly nervous now. Decided that I was going to hold a talk at Geek Girl Meetup Oresund and now I have to do it. Since I seems to be unable to hold lectures and lessons without knowing monumentally more than what I’m actually going to talk about, I have quite a lot of work to do.

I have named the talk “How to go from idea to webapp in 15 minutes”, or something like it, and it is about how to set up grunt, SASS, and JavaScript structure in under 20 minutes. And also, the will be pictures of kittens, probably.

I hope someone shows up and I hope I do great and that the kittens are cute.

Problem: You have styles you want for regular screens, and styles you want for retina screens. Mostly images with different sizes, but sometimes font sizes or widths.

I was faced with this recently and got annoyed at the amount of repeating I had to do. First it’s the fuck ugly syntax of the media queries, then it’s the browser compatibility, and then I have to repeat it all over my Sass document for different screen sizes and everything else that can change

Queue trying to build a handy mixin for it all

This is what I came up with:

@mixin retinaspecific($maxwidth, $attribute, $value) {
    @media
        only screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: $maxwidth),
        only screen and ( min--moz-device-pixel-ratio: 2) and (max-width: $maxwidth),
        only screen and ( -o-min-device-pixel-ratio: 2/1) and (max-width: $maxwidth),
        only screen and ( min-device-pixel-ratio: 2) and (max-width: $maxwidth),
        only screen and ( min-resolution: 192dpi) and (max-width: $maxwidth),
        only screen and ( min-resolution: 2dppx) and (max-width: $maxwidth) {
        #{$attribute}: $value;
    }
}

It’s a mixin that takes three arguments. The first ($maxwidth) handles the actual media query and when the rule should be applied. The second ($attribute) handles what attribute is affected. Here you put font-size, background-image or something like it. And the last one handles the value of the attribute, so what size should the font be, or what background image do you want.

It is quite handy! Just use it whenever you want something styled for a retina screen. Since you can reuse it for all attributes and screen sizes, it shourtens the code you have to write quite a lot.

Using it like this:

@include retinaspecific(500px, min-width, 55px);

Will compile to this:

@media 
    only screen and (-webkit-min-device-pixel-ratio: 2) and (max-width: 500px),
    only screen and (min--moz-device-pixel-ratio: 2) and (max-width: 500px),
    only screen and (-o-min-device-pixel-ratio: 2 / 1) and (max-width: 500px),
    only screen and (min-device-pixel-ratio: 2) and (max-width: 500px),
    only screen and (min-resolution: 192dpi) and (max-width: 500px),
    only screen and (min-resolution: 2dppx) and (max-width: 500px) {
        min-width: 55px;
}

I used it for my app Counting Down and as far as I know it doesn’t work in LESS

This may not be the easiest way to achieve this results, but I wanted to share it because it was genuinely awesome.

I wanted to put a bottom margin on all elements, except the last one, and I wanted to do it using nested LESS-syntax. Sure, I could just write two rules, one that put the bottom margin on all elements, and one that removed it on the last child. Like this:

.content {
  margin-bottom: 30px;
  &:last-child {
    margin-bottom: 0;
  }
}

But where’s the fun in that? No learning = no fun.

I couldn’t wrap my head around it, so I turned to StackOverflow and got exactly the kind of answer I wanted. User BoltClock explained and here’s what I learned:

What I wanted to do was to select all elements that were children of .content, but not the last one, so I had to select all children with the child selector > , then single out the last one with :last-child and put it in the :not-selector. Like this:

.content {
  > :not(:last-child) {
    margin-bottom: 30px;
  }
}

Which in its turn compiled to:

.content > :not(:last-child) {
  margin-bottom: 30px;
}

In the end I had to abandon it because there was an IE8 requirement in place. IE8 causes so much sadness.

I woke up one morning and didn’t care anymore. Didn’t feel anything when I thought about my future. Didn’t feel anything when I looked at people i knew I loved. It felt like the resonance I had felt in my chest when I looked at someone I loved was gone. It was like all feelings had disappeared. Except for fear. I got so scared that I panicked, and pressed myself against a wall and knew that I couldn’t survive this. There was no way I could feel like this and live through it. I was so scared.

This had happened before, but this time there was someone with me who knew that help could be gotten. And we did. I never pictured myself going to the psyciartic emergency room, but there I was. It was everything I expected it to be. Ugly. Run down. Sad. But then it wasn’t. Because there were people there who cared and knew how to help. They were concerned and I got medicine. I got sedatives and my self image changed. Now I was the kind of person who needed sedatives. And they were awesome. And I got antidepressants and it made it worse. It got so bad that there were times when I literally couldn’t stand on my own. At times I forgot to breathe. Apparently that’s how the medicine works. It makes it worse to be able to make it better.

And it got better, but man it was slow. So slow that I didn’t notice it. I had to force myself to wake up early and go running in the mornings and I’m so glad I did, I think it helped a lot. I figured out that the most difficult I could do was to be bored and be okay with it, when my mind wasn’t occupied it wandered away and always ended up in the worst “what if” it could find. Scumbag brain. So I played Minecraft and watched Lord of the Rings’ extra material.

And one day I woke up and it was fine. Only it wasn’t one day suddenly, it snuck in under the radar. I could feel love, I could feel happiness and I could think about the future without panic.

I hate you panic, but you helped me learn a lot about my brain and how it works. How it can’t always be trusted. That it sometimes makes stuff up just so that it can release some of the fear. I know that five people with the same length of shorts in a group aren’t dangerous, but when my brain was sick it couldn’t find any lions in its vicinity so it took the next best thing. People in shorts. Or christmas lights in the summer.

And even though it was aweful and I didn’t think I could survive, I did. I realized I am stronger than I realize and that medication really can help. They don’t change you, they don’t make you happy, but they do help you not panicking and getting up in the morning. In the long run it was probably a period that helped me grow. I learned that sometimes, when something seems absolutely impossible, it is the brain that fools me into hopelessness. I learned not to trust myself at times when I didn’t make any sense. And I learned that I could take help and that sadness, depression and panic doesn’t describe who I am. I got sick and I got better. It is a disease and it can be treated, even though the future hopefully will bring medicine with less side effects. I am not defined by my sadness and I can be content.

Thank you Erik, for all the help. I love you