Constraining images with CSS

Small details make a big difference to websites. It’s never a good look when an image is larger than its container. Fortunately, it’s very easy to fix.

Responsive websites are great; mobile-first websites are even better. However, they do sometimes present frustrating issues. One issue which props up on a fairly regular basis is the issue of images – more specifically, a question along the lines of:

Why don’t my images fit on the page?

It’s a simple question really – if text can adapt to fit on a smaller screen, why do images sometimes insist on maintaining their original size? The answer is very simple.

Here’s a fairly average piece of code for an image:

<img src="image.png" alt="Image" width="800" height="200">

When displayed on a website, that image will display at a resolution of 800 pixels wide by 200 pixels high. If you’re using a screen with a lower resolution, the text will be scaled down and the image will dwarf the rest of the content. That’s because, without any other information, the browser doesn’t know any better.

So, to get around it, you need to add the following CSS:

img {
 max-width: 100%;
 height: auto;
 }

This does two things. First, it constrains all images to the maximum screen width. If that is 320 pixels, that’s the size the image will be scaled to. Second, it constrains the image height proportionally, so the image doesn’t look like it’s been squished.

So, what if you need to constrain not just images, but videos, and possibly more besides? Easy. Change your CSS to this:

.constrain {
max-width: 100%;
height: auto;
}

Now, you can use the .constrain class on any element and it will be constrained to the intended width.

Automating Linux website creation

I create a lot of test websites. Sometimes it’s for testing new things, other times it’s for testing upgrades. I’ve always found it’s a hassle to set a new website up, so I’ve tried to automate it.

Back in the days of shared hosting, setting up a new website was easy. It was as simple as:

  1. Set your nameservers to those of your web host;
  2. Log in to their system (usually cPanel) and click something like “New domain” or “New subdomain”.

Since I moved to using a VPS, it’s not as easy as that any more. Firstly, I use CloudFlare, so I use their namservers. Secondly, I don’t run cPanel, or Plesk, which is similar. There are two reasons I don’t use them:

  1. They make hosting more expensive, as they require licences;
  2. They further increase cost as they require much more powerful servers to run.

Currently I can run my VPS for about $5 per month. If I used cPanel or Plesk, they would cost about $50 per month. So, if I can do without, it’s a big saving.

Setting up a new website

There are a few things required in setting up a new website (I won’t cover setting up a VPS – that’s another series I’m working on):

  1. You need a user to own the files;
  2. You need to create the required directory structure and set permissions on it;
  3. You need to create a MySQL user and password;
  4. You need to create a MySQL database and control permissions to it;
  5. You need to set up the web server to make the address reachable.

I’ll assume the DNS is set elsewhere, or using a hosts file. I use Nginx as my web server.

That’s quite a few things to set up, and it would be easy to miss something or get a step wrong. Even if you get it right, it will take a few minutes. The longest part is usually setting up the web server – especially with Nginx that configuration is set centrally and isn’t easily overridden outside of that.

One day I got bored of doing it all manually, so I wrote a Bash script to take care of it. It’s not perfect, but it does a decent job. I decided I’d make it available via GitHub.

Currently, I make a folder it /opt/ and call it something like website-creator. I can run it as follows:

sudo bash /opt/website-creator/create-website.sh

When run, it does the following:

  • Prompts for the fully qualified domain name (FQDN) which will be used to access the website when it’s live;
  • Checks a folder for that FQDN doesn’t already exist (in a pre-determined folder);
  • Prompts for the Linux user who should own the folder for that website;
  • Checks to see if the user exists, and creates the user if it doesn’t;
  • Prompts for MySQL admin credentials;
  • Once authenticated, prompts for a database name;
  • Creates the database;
  • Checks for a MySQL user with the same name as the Linux user which should own the files, and creates a user with that username if it does not exist;
  • Gives that user access to the database which has been created;
  • Creates the folder structure (I use public, private, logs and backups);
  • Copies index.html and 404.html files to the web root for that site;
  • If necessary, creates a file with the MySQL password for the newly-created user and places it in the private directory, with read-access to the owner only;
  • Changes the owner of the website folder structure to the Linux user previously specified (including the file with the MySQL password);
  • Copies a template Nginx configuration to the sites-available directory;
  • Runs a search and replace on that file to insert the domain name and root directory;
  • Activates the site (placing a symbolic link in sites-enabled);
  • Reloads the Nginx configuration;
  • If necessary, prints to the screen the password of the new Linux user.

It’s not perfect, but it does mean I can set up a working website in five seconds, rather than five minutes. There are, of course, some things that may need to be changed once it’s done, like modifications to the site’s Nginx configuration, but without changing anything, it will happily serve static and PHP content.

There’s also a file where runtime variables can be stored. At the moment, it has two:

  • WEBROOTFOLDER – this is the folder the website directories will be created in (I use /usr/share/nginx/);
  • NGINXCONFIG – this is where the Nginx configuration is stored (in Ubuntu, that’s /etc/nginx/, but it may be different on other systems).

It makes my life a lot easier. Maybe it will help a few other people too.