f w h

Solving Common Design Problems Using CSS Calc()

CSS’s calc() property is one of the lesser known but most useful around. It can solve a number of the more common front end code issues we face, and browser support is surprisingly deep.

First, let’s take a look at how calc() works. calc() can be used in place of any length, frequency, time, number or integer. If, say you wanted to set the width of an element to 90%, but subtract 20 pixels to compensate for another element, you would write it like so: width: calc(90% – 20px);

Note the spaces between the numbers and the operator. The expression will not work without them. It is possible to create more complex calculations and nest parentheses. See the spec for more information.

Compensate for Margins

Say you have 5 elements across, each sized at 20% width, but you need to add a 5px right margin on each for spacing. Add the margin-right:5px; as you normally would. Then, calculate the width like so: width:calc(20% – 5px);

Calculate Width for X Number of Elements

Calculating width for the 5 elements I mentioned above can be done more easily. Simply divide 100% by the number of elements like so: width:calc(100% / 5);. Incorporate the margin compensation, if necessary: width:calc((100% / 5) – 5px);. If rounding errors are a problem, use 99.9% in place of 100%.

Static Width Element + Fluid Width Element + Responsive

Perhaps your right sidebar needs to remain a fixed width, but you need the content area to be fluid. Consider the following HTML:


<aside class="sidebar">
	<!--Sidebar content-->
</aside>
<section class="main">
	<!--Articles and what-not-->
</section>

Let’s say we want the sidebar to be a static 150px wide, but the content area to fit the rest of the area and remain fluid. The relevant CSS would look like this:


.sidebar{
	float:right;
	width:150px;
}
.main{
	float:left;
	width:calc(100% - 150px);
}

Centering Elements Vertically and/or Horizontally

There are a plethora of ways to center elements, and this is really just an easier way to do the old left:50%; with a negative half margin trick:


div{
	width:100px;
	position:relative;
	left:calc(50% - 50px);
}

These are just a few of the really common front end design problems. The possibilities are endless. What other uses cases do you know of?

Quickly Set Up a Local WordPress (Linux)

I do a lot of work on WordPress, so I find myself downloading the latest copy and setting it up fairly often. It helps to have simple scripts to do these things.

The concept here is to create a shell script that downloads and extracts WordPress to the current folder. We also want to be able to run the script from any folder.

Set the Stage

First, in your home folder, create a new folder called bin. Inside that folder, create a new blank file called wordpress.sh.

Add the Script

Inside the file you just created, add the following script:


#!/bin/bash

sudo wget http://wordpress.org/latest
sudo tar -xvzf latest*
cd wordpress
sudo cp -R * ..
cd ..
sudo rm -rf wordpress/
sudo rm -rf latest*

Save the script, then make it executable by opening your terminal, navigating to ~/bin and running the following command:


sudo chmod -x wordpress.sh

Run the Script from Anywhere

Now, we just need to add the script to the path so we can execute it from anywhere. Run the following command:


export PATH=$PATH:$HOME/bin && echo 'export PATH=$PATH:$HOME/bin >> ~/.bash_profile'

Run the Script

Create a new folder, navigate to it in the terminal and type wordpress.sh. The script will download and extract the latest version of WordPress for you.

What’s Next?

I personally use PHP’s built in server along with a custom domain to develop, so I’ll run sudo php -S roe.dev:80, then go to http://roe.dev in my browser. One could add that line to the shell script just to make the process that much smoother.

Halt Comment Spam in WordPress

The spam comments on this blog got ridiculous. Readers never saw it because I moderated all of them. However, I was receiving 60-80 comments per day, and it took too much to try and sift through for legit comments (I’m sorry if you’ve commented here and it never got posted. I tried).

I was pretty well fed up with it, so I tried plugin after plugin. One made it impossible for anyone without an account to post comments, one didn’t work at all, and I didn’t want to pay for an Akismet key (so I’m cheap, what of it?).

How then, does one take care of this problem? I looked at a number of alternatives. Some possibilities were an “Are you human?” checkbox or Q&A (answer a question like what is 2+4) or traditional image CAPTCHAs. But, I knew I wanted one thing for sure. I didn’t want to put the burden on real people. So, I decided to go with the “honeypot” or invisible CAPTCHAs.

The idea is that because spam bots love to fill in input fields, you can hide one with CSS and halt form submission if the field has a value. Initially, I tried doing this with some fairly simple JavaScript. Intercept the submit button click and return false if the field has a value. Easy, right? Nope. As it turns out, spam bots ignore JavaScript, and there was no change in the amount of spam.

It had to be on the backend. Because I don’t particularly care what a commenter’s website is, I chose that field as my honeypot, and used CSS to hide it from the user’s view. In WordPress, comment submission is handled by wp-comments-post.php in the root. I then added the following to that file at line 82:


if (strlen($comment_author_url) > 0){
	die("Fail sauce");
}

Why line 82? This is after the user information is gathered and stored in variables, but before any actual action is taken. Admittedly, it took a bit find the correct variable I had to use. I certainly could have just used $_POST[‘url’], but I feel like the variable should be used to keep the code consistent. What we’re doing here is taking the number of characters in the website field, and if that number is greater than zero, halting the code from continuing.

Results

The number of spam comments for about the last two years has ranged between 60 and 80 per day. Since implementing this honeypot CAPTCHA 3 weeks ago, I’ve received one spam comment.

One Major Issue

As some might guess, the major issue with this method is that updates to WordPress will very likely undo it. I think that’s a small price to pay for the results.

UPDATE (18 Jan 2014)

As suggested in the comments, I’ve worked out a way to add this CAPTCHA scheme to a theme’s functions.php file. Just add this to the file:


add_filter('pre_comment_approved', 'check_honeypot');
function check_honeypot() {
    if (strlen($comment_author_url) > 0) {
        die("Fail Sauce");
    }
}

This will keep WordPress updates from breaking it.

Mobile and Touch Friendly Text Links

Here’s a quick trick to make text links, specifically paragraph text links more mobile and touch friendly:

The Concept

Apple recommends a minimum 44px square for touch interface links. We’re going to use a pseudo-element (doesn’t matter which) to create links with larger touch areas. It turns out that a pseudo-element that is tied to a “clickable” element (link, button, etc.) is clickable as well (h/t Chris Coyier for pointing that out).

Essentially, we need to absolutely position the pseudo-element within the link, make it 44px tall X 100% wide. Then, shift the pseudo element partially above the link using a negative top value.

See the pen below. I’ve added an outline around the pseudo-element to show its larger surface area.

Check out this Pen!

Detecting Mobile Browsers in jQuery Without Browser Sniffing

The Concept

Using jQuery’s .css() method, we’ll detect whether a media query has been triggered, and run our code based on that.
The HTML for this is irrelevant. You could use any element for it. You could even just use an element you’re already altering with a media query. For this guide we’ll just use this:


	<div class="hideForMobile"></div>

Now, in CSS, we’ll set a media query to hide this div on mobile:


@media (max-device-width:480px){
  .hideForMobile{display:none;}
}

And now, let’s make the magic happen:


$(document).ready(function(){
  // Grab the value of the display property and store it in a variable
  var mobileTrigger = $('.hideForMobile').css("display");
  // If the display is set to "none", run our code
  if (mobileTrigger=="none"){
    // Code to run
  }
});

Applications

This could be used to run (or prevent running) just about any code that you want. It can also be set up to work with any element and any CSS property, as long as you’ve set that property in your media query.

Update: Vanilla JS

Here is the long overdue update that doesn’t require jQuery:


function isMobile(element_selector, status){
  var e = document.querySelector(element_selector);
  if(getComputedStyle(e).display == status){
    return true;
  } else {
    return false;
  }
}

window.onresize = function(){
  console.log(isMobile('div.hideForMobile', 'none'));
}

The vanilla JS example uses the same HTML and CSS as the jQuery example.

« Previous PageNext Page »