The problem arose when I was making a website with an online store. Pictures of products on the pages have to be displayed identically, whereas the customer has pictures of all possible sizes and proportions. In order to free him from the image editing, it was decided to inscribe them in a container - <div> block of fixed size, framed with border. Horizontally elongated images will be inscribed by width, while vertically elongated ones - by height respectively. The images should be clickable.

Actually, the problem is quite typical and has existing solutions, for example, only using CSS-styles. However, when such a powerful weapon as a server-side code is in hands, it's a sin not to use it when you are rather a programmer than a designer. So I wrote a function that covers every possible aspect ratio of the container and inscribed image. Let me offer it to the public.

Let's call our function out_adjusted_link_image. Its definition will look like this:

function out_adjusted_link_image($img_file, $img_alt, $img_title,
                                 $a_href, $div_wd, $div_ht,
                                 $div_more_style = '', $a_more = '')

Parameters:

Name
Type
Description
$img_file
string
path and name of image file
$img_alt, $img_title
string
alt and title attributes of the image tag
$a_href
string
URL opened by clicking on the picture
$div_wd, $div_ht
int
width and height of the container
$div_more_style
string
Additional attributes of the container's CSS-style (optional)
$a_more
string
additional attributes of anchor tag (optional)

Function return value - string containing HTML-script of our construction container - link - image.

We build the body of the function. Step by step:

1. Define the constants that specify both dimensions by which we inscribe:

define('ALIGN_BY_WD', 0);
define('ALIGN_BY_HT', 1);

2. Find image size. To do this, use the function getimagesize(). As an argument, this function requires the image file name, including path to it. It returns an array of 7 elements, of which we are interested in the first two (ie indexes 0 and 1) containing respectively the width and height of the image.

$size = getimagesize($img_file);
$img_wd = $size[0];
$img_ht = $size[1];

3. Determine which dimension will be used to inscribe. If the container is more vertically "flattened" than the image, so after adjusting the size the image will be fit by height, otherwise, - by width. This logic is implemented in the following PHP code snippet:

if ($div_wd / $div_ht > $img_wd / $img_ht)
  $align = ALIGN_BY_HT;
else
  $align = ALIGN_BY_WD;

A special case when proportions of both rectangles are equal, and you can align in any dimension, is processed in the else block.

4. Now we can inscribe our picture into container. To do this, we calculate the width and height of the inscribed image - $new_img_wd and $new_img_ht. For subsequent centering also define variables $rel_edge and $abs_edge - edges for relative and absolute positioning on relevant measurements, and $new_img_dim - the size that will be used to set the indent. Assign values ​​to them in accordance with the directions of alignment.

if ($align == ALIGN_BY_HT) {
  $new_img_ht = $div_ht;
  $new_img_wd = $new_img_ht * $img_wd / $img_ht;
  $rel_edge = 'left';
  $abs_edge = 'top';
  $new_img_dim = $new_img_wd;
}
else {
  $new_img_wd = $div_wd;
  $new_img_ht = $new_img_wd * $img_ht / $img_wd;
  $rel_edge = 'top';
  $abs_edge = 'left';
  $new_img_dim = $new_img_ht;
}

5. Center the image. Picture inscribed by width will be vertically adjusted, while the one inscribed by height - horizontally. To do this, use the technique of alignment as described in the previous article. Assign the required string of style to the variable $img_style:

$img_style = 'position:absolute; ' . $rel_edge . ':50%; width:' .
             $new_img_wd . 'px; height:' . $new_img_ht . 'px; margin-' .
             $rel_edge . ':-' . ($new_img_dim / 2) . 'px; ' .
             $abs_edge . ':0';

Now we can build a whole structure container - anchor - image, and such a string will be returned by the function:

return '<div style="position:relative; width:' . $div_wd .
       'px; height:' . $div_ht . 'px; border:1px solid silver;' .
       $div_more_style . '"><a href="' . $a_href . '" '. $a_more .
       '><img src="' . $img_file . '" alt="' . $img_alt . '" title="' .
       $img_title . '" style="' . $img_style . '" /></a></div>';

Here's how this structure looks in a browser:

Monkey

Have we achieved the desired result? Not really. Try to move the cursor over our block and see that the margins between the image and the edges of the container are beyond the link. To ensure the link to cover the entire block, do the following:

  1. Place our inscribed and centered image before the link anchor.
  2. Instead, place transparent PNG-image inside the anchor, and specify the size of this image to be the same as the size of the container.

Thus, our picture becomes overlapped with the transparent image and remains visible yet. The zone of link action expands to fill the container.

The modified code snippet that returns the value of the function takes the following form:

return '<div style="position:relative; width:' . $div_wd .
       'px; height:' . $div_ht . 'px; border:1px solid silver;' .
       $div_more_style . '"><img src="' . $img_file . '" style="' .
       $img_style . '" /><a href="' . $a_href . '" '. $a_more .
       '><img src="images/Transparent.png" alt="' .
       $img_alt . '" title="' . $img_title . '" width="' .
       $div_wd . '" height="' . $div_ht .
       '" style="position:absolute; top:0px; left:0px;" /></a></div>';

Place your cursor now and experience the difference:

Monkey

Bringing together all of the above code parts, we get the function in its final form:

function out_adjusted_link_image($img_file, $img_alt, $img_title,
                                 $a_href, $div_wd, $div_ht,
                                 $div_more_style = '', $a_more = '') {
  define('ALIGN_BY_WD', 0);
  define('ALIGN_BY_HT', 1);
 
  $size = getimagesize($img_file);
  $img_wd = $size[0];
  $img_ht = $size[1];
 
  if ($div_wd / $div_ht > $img_wd / $img_ht)
    $align = ALIGN_BY_HT;
  else
    $align = ALIGN_BY_WD;
 
  if ($align == ALIGN_BY_HT) {
    $new_img_ht = $div_ht;
    $new_img_wd = $new_img_ht * $img_wd / $img_ht;
    $rel_edge = 'left';
    $abs_edge = 'top';
    $new_img_dim = $new_img_wd;
  }
  else {
    $new_img_wd = $div_wd;
    $new_img_ht = $new_img_wd * $img_ht / $img_wd;
    $rel_edge = 'top';
    $abs_edge = 'left';
    $new_img_dim = $new_img_ht;
  }
 
  $img_style = 'position:absolute; ' . $rel_edge . ':50%; width:' .
               $new_img_wd . 'px; height:' . $new_img_ht . 'px; margin-' .
               $rel_edge . ':-' . ($new_img_dim / 2) . 'px; ' .
               $abs_edge . ':0';
 
  return '<div style="position:relative; width:' . $div_wd .
         'px; height:' . $div_ht . 'px; border:1px solid silver;' .
         $div_more_style . '"><img src="' . $img_file . '" style="' .
         $img_style . '" /><a href="' . $a_href . '" '. $a_more .
         '><img src="images/Transparent.png" alt="' .
         $img_alt . '" title="' . $img_title . '" width="' .
         $div_wd . '" height="' . $div_ht .
         '" style="position:absolute; top:0px; left:0px;" /></a></div>';
}

Here is an example of the function call. It renders in your browser this nice monkey inscribed into the clickable square:

echo out_adjusted_link_image('images/monkey.jpg', 'Monkey', 'Monkey',
                    '#anchor', 200, 200,
                    'left:50%; margin-left:-100px', 'target="_blank"');

Here the container itself is also centered horizontally within its own parent block in the same manner.

In one of the later articles I'm planning to explain, how I embed this code into the content of material in Joomla website.

Users must be registered and logged in to post comments.

By working with this site, you agree to our use of cookies necessary to keep the settings you select, as well as for the normal operation of Google services.