Keeping an images ratio on resize in JavaScript

A little tricky task was given to the team I am working in, to keep an image at its aspect ratio. However the catch is that it needs to be able to go as large as it can to fill the screen at all times, while the user can resize the screen and keeping the images size ratio. Easy you may say, but once you get into it, not so much.

Three of us thought long and hard through many different situation of how we can calculate the size, detect the users actions and calculate the ratio, but with no luck. We also then hunted the internet as all great developers do, which produced many methods using some very long calculation, but none just seemed to work and we knew nothing about the maths.

Then like a shine of light I thought of how you can do it in a simple way. Instead of thinking of the image at 1980px by 1020px and then calculate out the pixel difference etc, you need to think about the image in percentages. When you reduce the images width by say 594 pixel, you would then think of how to calculate the relative pixel difference on the height of the image, but this would be going in the realms of mathematicians. Therefore you stop thinking of that in pixels and think that 1980px reduced by 594px, is a 30% reduction.

Now all you need to do is reduce the height also by 30%, relative to the heights pixels, so here we go…

First we need to find out what the width and heights relative 1% is, so we know where to work from. You need to provide the images original height and width to start this off, then divide each by 100, simple maths.

// Get the one percent of the image width and height
var widthOnePercent = imageOriginWidth / 100;
var heightOnePercent = imageOriginHeight / 100;

Next because we want the image to be as large as it can, we will set the width to be as large as the container to start off the calculations. Once this has been set we can use the images size to find out what percentage the width is at. We know the width of what the image is at in pixels and we know how many pixels are 1%, therefore we can divide the images width by 1%. For example 1386px divided by 19.8px equals 70%.

// Calculate the width percentage
var imageCurrentWidth = $(imageSelector).width();
var imageCurrentPercent = imageCurrentWidth / widthOnePercent;

Now we just need to set the height of the image to 70% of the images height, by multiplying the images 1% height by 70%.

// Calculate the height relative to the percentage of the images width
var imageNewHeight = heightOnePercent * imageCurrentPercent;

However this will work to put the image within the width boundary of the container and the images ratio kept in tact, but potentially due to the width the height could be off the screen. Therefore we need to make sure the image doesn’t go off the screen. This can be calculated out by checking if the height of the image, plus the distance from the top of the window, is not as large as the windows height.

($(window).height() < $(imageSelector).offset().top + imageNewHeight)

Once we have determined this, then we do the same as before but in the opposite direction. This time we start with what height we want the image to be, instead of what height it is. To do this we use the windows height, minus the images top offset, which gives use what space is left.

// Set the new height so it fit on the screen
imageNewHeight = $(window).height() - $(imageSelector).offset().top;

Then the same as before, it is divided by the images 1% height to calculate what the percentage the width is going to be.

// Calculate out what percentage is the height at
imageCurrentPercent = imageNewHeight / heightOnePercent;

// Calculate the width relative to the percentage of the images height
var imageNewWidth = widthOnePercent * imageCurrentPercent;

Below is the full JavaScript code, but to see a full example check out my PureRandom CodePen.

(function($) {

function calIamgeSize(imageSelector, imageOriginWidth, imageOriginHeight) {

// make image as big as it can to start
$(imageSelector).width(
$(imageSelector).parent().width()
);

// Get the one percent of the image width and height
var widthOnePercent = imageOriginWidth / 100;
var heightOnePercent = imageOriginHeight / 100;

// Calculate the width percentage
var imageCurrentWidth = $(imageSelector).width();
var imageCurrentPercent = imageCurrentWidth / widthOnePercent;

// Calculate the height relative to the percentage of the images width
var imageNewHeight = heightOnePercent * imageCurrentPercent;

// If the images height is off the page, then rescale
if ($(window).height() < $(imageSelector).offset().top + imageNewHeight) {

// Set the new height so it fit on the screen
imageNewHeight = $(window).height() - $(imageSelector).offset().top;

// Calculate out what percentage is the height at
imageCurrentPercent = imageNewHeight / heightOnePercent;

// Calculate the width relative to the percentage of the images height
var imageNewWidth = widthOnePercent * imageCurrentPercent;

// Set new width of image
$(imageSelector).width(imageNewWidth);

}

// set new height of image
$(imageSelector).height(imageNewHeight);

}

// Resize image
var imageW = 1000;
var imageH = 667;
var imageClass = ".js-render-image";

$(window).on("resize", function() {

calIamgeSize(imageClass, imageW, imageH);

});

calIamgeSize(imageClass, imageW, imageH);

})($);

How to put items in a Circle in CSS LESS

Through the depths of the internet I have search and found a method to put items on a circle using a CSS preprocessor. However it was in SCSS and I work in LESS, by which I mean the preprocessor not just less things. So I have converted it over to the dark side of LESS and broken down how it works below, I hope this helps.

Let’s start off with the SCSS version of items on a circle by Hugo Giraudel from his site.

/// Mixin to put items on a circle
/// [1] - Allows children to be absolutely positioned
/// [2] - Allows the mixin to be used on a list
/// [3] - In case box-sizing: border-box has been enabled
/// [4] - Allows any type of direct children to be targeted
///
/// @param {Integer} $nb-items - Number or items
/// @param {Length} $circle-size - Container size
/// @param {Length} $item-size - Item size
/// @param {String | false} $class-for-IE - Base class name for old IE
@mixin distribute-on-circle(
$nb-items,
$circle-size,
$item-size,
$class-for-IE: false
) {

$half-item: ($item-size / 2);
$half-parent: ($circle-size / 2);

position: relative; /* 1 */
width: $circle-size;
height: $circle-size;
padding: 0;
border-radius: 50%;
list-style: none; /* 2 */
box-sizing: content-box; /* 3 */

> * { /* 4 */

display: block;
position: absolute;
top: 50%;
left: 50%;
width: $item-size;
height: $item-size;
margin: -$half-item;

}

$angle: (360 / $nb-items);
$rot: 0;

@for $i from 1 through $nb-items {

@if not $class-for-IE {
> :nth-of-type(#{$i}) {
transform: rotate($rot * 1deg) translate($half-parent) rotate($rot * -1deg);
}
} @else {
> .#{$class-for-IE}#{$i} {
// If CSS transforms are not supported
$mt: sin($rot * pi() / 180) * $half-parent - $half-item;
$ml: cos($rot * pi() / 180) * $half-parent - $half-item;
margin: $mt 0 0 $ml;
}

}

$rot: ($rot + $angle);
}

}

So now you have seen the SCSS, let’s go to the LESS CSS.

First lets build the method you will be calling in the CSS, which like most of this we will just be copying the SCSS. Instead of putting an action call before the method name like in SCSS (@mixin), we call it like a class in standard CSS. In LESS we also identify variables with ‘@’ instead of the ‘$’. This means the above method of calling a method turns into the below.

.on-circle(@item-count, @circle-size, @item-size) {

}

There are then some manadatory styles that we need for the container to work. At this point though you could also add in some of your own custom style for the container as well. When we call the method we will be putting it in the containers class. We also use the variable ‘circle-size’ for the width and height. For this I used the Unit function for LESS, so it could be swapped out to be in percentage, em, rem or anything else. Rembering to use the ‘@’ to call the variable and not the ‘$’.

.on-circle(@item-count, @circle-size, @item-size) {

position: relative;
width: unit(@circle-size, px);
height: unit(@circle-size, px);
padding: 0;
margin:auto;
border-radius: 50%;

}

Within the method we now call upon the children, but to make sure we only affect the children of the container and nothing further down we got the direct child symbol added in (‘>’). Also because you could be using div’s, span’s or li elements as the children, it using the any type of element selector (‘*’).

A method to centre items up, which we have used here, is to set the width and height 50%, then move the item back half of its size. We get the children’s item size sent in the method to use for this, plus we got the Unit function used in case your making this responsive.

> * {

display: block;
position: absolute;
top: 50%;
left: 50%;
width: unit(@item-size, px);
height: unit(@item-size, px);
margin: unit(-(@item-size / 2), px);

}

Next is the loop for each child and it gets a bit different here for the conversion so ill break it down a bit more. The loop in SCSS looks more like a general loop you would see in JavaScript or some other languages, but the way to do in LESS is to call it like a method with an exception on the side. You can see from the example below I have called the method ‘cl’ for ‘children loop’, passed in two variables and then put a when clause on the side. This will then run while ‘i’ is greater than zero.

.cl(@i,@r) when (@i > 0) {

}

However this will be an infinite loop at the moment as ‘i’ never changes and if we just change ‘i’ in the loop then the ‘when’ clause won’t know about it. What we can do is call the loop method again inside, but of course minus 1.

Our ‘i’ variable is going to be our item count as we want to loop through each of the items. The second variable is our rotation for the item we are at, so for this reason we need to calculate out how much rotation we need for each item. This will be 360 degree’s divided between how many items we have, which will give us the 1% rotation value for each item on the circle.

You can then see we call the method at the bottom after we create the method, or the LESS won’t know what you are calling. Then in each iteration we iterate the variables by removing 1 from the item count and adding another degree percentage to the previous degree.

@angle: (360 / @item-count);

.cl(@i,@r) when (@i > 0) {

@rot: @r + @angle;
.cl(@i - 1,@rot);

}

.cl(@item-count,0);

We can now convert in the style for each of the children items, which is added in the loop. The simple conversion differences are the variables in the nth-of-type and the degrees. Instead of the ‘$’ symbol we use the ‘@’.  Then compared to the SCSS version, I did the calculation within the translate instead of using a variable. I halfed the circle and again to make it flexible to change I used the Unit function.

&:nth-of-type(@{i}) {

transform: rotate(@r * 1deg)  translate(unit(@circle-size/2,px)) rotate(@r * -1deg);

}

All Together Now

At the end of the road with all the pieces we have the final product. You can then use the following as the base to build your items in a circle. I have done a small demo on my Code Pen here.

/// Mixin to place items on a circle
/// @author Hugo Giraudel
/// @author Ana Tudor
/// @author convert SASS to LESS Christopher Pateman

.on-circle(@item-count, @circle-size, @item-size) {

position: relative;
width: unit(@circle-size, px);
height: unit(@circle-size, px);
padding: 0;
margin:auto;
border-radius: 50%;

> * {

display: block;
position: absolute;
top: 50%;
left: 50%;
width: unit(@item-size, px);
height: unit(@item-size, px);
margin: unit(-(@item-size / 2), px);

@angle: (360 / @item-count);

.cl(@i,@r) when (@i > 0) {

&:nth-of-type(@{i}) {

transform: rotate(@r * 1deg)  translate(unit(@circle-size/2,px)) rotate(@r * -1deg);

}

@rot: @r + @angle;
.cl(@i - 1,@rot);

}

.cl(@item-count,0);

}

}

 

View the Source Code of Mobile Devices

Do you need to know what you mobile website is producing, but on the phone itself? Then here are the best ways I have found to inspect you mobile phone or tablets HTML. I have found how to inspect the HTML source of multiple platforms including iPhone, Android and more.

iOS (iPhone/iPad)

Let’s start with the best one and that is the iPhone and iPad. This only works on these devices and is totally worth it. Start by bookmarking the page you are on and calling it ‘View Source Code’ or what ever you want to call it.

Once you have it bookmarked, copy the JavaScript below into you clipboard. Now go to the bookmark you just created and edit the URL. Delete the URL currently in the field and overwrite it with the JavaScript you just copied.

javascript:(function(){var d=window.open(‘about:blank’),a=d.document;a.write(‘<!DOCTYPE html><html><head><title>Loading Source</title></head><body></body></html>’);a.close();var b=a.body.appendChild(a.createElement(‘form’));b.setAttribute(‘method’,’post’);b.setAttribute(‘action’,’http://ole.michelsen.dk/viewsource/?uri=’+location.href);var c=b.appendChild(a.createElement(‘input’));c.setAttribute(‘type’,’hidden’);c.setAttribute(‘name’,’DOM’);c.setAttribute(‘value’,encodeURIComponent(document.documentElement.innerHTML));b.submit()})()

Now when you go to a website you want to view, simply select the ‘View Source Code’ bookmark and a new tab will open with your HTML in.

Android

Another one I have found for Android is much simpler, but has not been fully tested by myself as I am an iPhone user. If you copy the code below into you clip board, then paste it in the address bar of the website you wish to see the source code of.

javascript: alert(document.getElementsByTagName(‘html’)[0].innerHTML);

Once loaded you should be able to see the HTML source of that page. This method is simpler than the iOS, but you will have to have this snippet saved somewhere to keep entering it.

Through the code

If you have access to the code then you can simply add the above code in the JavaScript tag to alert the HTML, but it doesn’t work that well. If you alert the whole HTML then it shows you as much as it can, but as there is so much HTML it doesn’t show everything.

 alert(document.getElementsByTagName(‘html’)[0].innerHTML);

Windows Phone

I have not found a way to view the source code on a Windows Phone yet, but if anyone knows then please comment here to help others.

Which Viewport Width?

Responsive designs are the current and the future, but how do you build yours? When you build a responsive website one of the key parts is the view port. This tells the browser details on how to view the website it is requesting. The question is what do you tell it?

Lets start with his it looks and what is available in this tag. The viewport is a meta tag that contains the data as you can see from below.

<meta name=”viewport” content=”width=device-width, user-scalable=no,maximum-scale=1,initial-scale=1″>

The width defines how the browser views the website in scale. The discussion I bring is do you specify the width or do you leave it to the device width to decide?

If you use the ‘width=width-device’ then the width of to website will be scaled to the width of the device. So if you phone is 365px like the iPhone, then you website will be displayed with that width. This is how I describe fully responsive as, if you are going to design and build in this way then the website will responded to the width of the device. The thing is though this comes with it’s own con’s and pro’s of use.

//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

(adsbygoogle = window.adsbygoogle || []).push({});

Pro’s

The pro’s of using this method is that when you build this amazing website you can take pride in the build. You did it the difficult way, but the most fluent way. When you scale down your website you will see the transition down to the specifically designed mobile view. It is an excellent thing to put on you CV as it shows the level of skill to make sure that as you shrink your window everything stays inline and in all browsers.

Con’s

Although this is all good, it is still the hard way about it. If you have just done an amazing mobile perfect design and then Samsung brings out a new bigger phone, then your design changes. You can have a fully responsive website and please every device, as they are all different width and heights. In the end you start to compromise you design to make it better for all browsers and easier to build, which is never what you want to do.

 

The other method would then be setting the device width to a pixel size. This would mean if you built you website to 767px(phablet) then all devices will view the website at that width. The browser will just scale the content to the device size. The sort of problem is you then rely on the JavaScript to set it for the correct device. As a .net developer, I used a number of method to detect the device size and failed, there fore I had to use JavaScript. The problem I have with this is, like I said in a previous post, what if that person has JavaScript off or the company they work for blocks JavaScript on their proxy. These days this is not a problem, so you can use it and I have it attached below.

//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

(adsbygoogle = window.adsbygoogle || []).push({});

So back to the attribute width and the pro’s/con’s of using it.

Pro’s

You do one design and that will be the design of all of the devices. This then get consistency and makes sure everyone views the intended design. This also makes it easier to develop for as you don’t have to build for all devices, just one which is one size. If you make the container 767px width and the viewport 767px, then it will view it like that.

Con’s

It is just not as elegant. You will basically be building different websites, which doesn’t feel like you are building responsive. I would say this method is mobile optimised only. This shows skill level but I wouldn’t think as much as a fully responsive build.

//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

(adsbygoogle = window.adsbygoogle || []).push({});

Which method do you use and why?

Viewport example

<meta name=”viewport” content=”width=device-width, user-scalable=no”>

JavaScript for screen size

        if (window.innerWidth

            // Phone

            document.querySelector(“meta[name=viewport]”).setAttribute(‘content’, ‘width=767; user-scalable=0’);

        }

        else if (window.innerWidth

            // Tablet

            document.querySelector(“meta[name=viewport]”).setAttribute(‘content’, ‘width=1024; user-scalable=0’);

        }

   

 

UPDATE

I have found a bug in Windows phones that are just not listening to the viewport. So after a long look into why and how to fix I have found the solution!!

As well as the viewport meta tag you need to also set the ‘HandheldFriendly’ and ‘MobileOptimized’ meta tags as below:

<meta name=”HandheldFriendly” content=”false” />
<meta name=”MobileOptimized” content=”device-width” />

These help as they are the orginal tags, but the way to fix the whole problem is by CSS. when you do your media tag in your Stylesheet, you must use device with like below:

@media screen and (max-device-width:767px){}

This will capture the Windows phone as it doesn’t listen to just ‘max-width’. once you then have this in you can set the viewport vis CSS as demostrated.

This is the plain CSS below:

@-webkit-viewport{width:1024px}
@-moz-viewport{width:1024px}
@-ms-viewport{width:1024px}
@-o-viewport{width:1024px}
@viewport{width:1024px}
 

The full example is:

@media screen and (max-device-width:767px){
@-webkit-viewport{width:767px}
@-moz-viewport{width:767px}
@-ms-viewport{width:767px}
@-o-viewport{width:767px}
@viewport{width:767px}
}

user-scalable

This is the key to if the user can zoom in and out of the website page. If you have created a great mobile optimised website then the user shouldn’t have to zoom in. Also if the website would break if you do zoom in then it would be wise not to let them do that. You may however want then to scale in so they can read text easier, have a closer look at an image or just get a better view, but then this is not a good mobile website.

initial-scale

This is the same as the above attribute, but it’s how it starts. This could be good if you don’t have a mobile optimised website, to have it zoomed in on a welcome paragraph.

maximum-scale

The attributes before do the scaling, but this attribute will tell the website how much it is aloud to scale to. This can then give the user the flexibility to zoom, but not enough to ruin the websites appearance.

Responsive decided

The battle field was laid out and the fight between the quick, safe, easy  fixed viewport and the reliable, standard responsive viewport was a foot. Then walked in the boss… Google. Recently Google has decided which method you must follow to get good rankings on its search engines. Is it the best choose? And should Google get to decide?

Fixed or Responsive Viewport Post

I recently posted about both methods and how they both have their pro’s, but also their con’s. The fixed method was amazing for the designer and developer to get a design for all devices created then developed. This would then view flawlessly on all devices. The implementation of this was also simple with some simple JavaScript and the viewport. The trouble came when we cross browser tested it as some of the browser of some devices didn’t listen to the viewport in the same manner. We fixed the most popular browsers and made fixes for the others. This I always felt was a work around and not the best method, but it worked very well, much faster and meant we could give a true design to the client.

On the other hand we had the other method, which was to set the viewport to device-width. This meant we had to make sure the website worked in all device sizes. This then also meant we couldn’t have one true design, so it would come down to how we could make the website breakdown in a smooth creative way, that also looked amazing. The time to slowly do this and test on multiples devices takes longer, not much but enough to notice. It also relies on the developer knowing good design, good code and best practices. Then again it is worth it as it makes a better website I think and a better developer. If you can envision how the given design can breakdown over all the pixel range and still have a great design look then it shows you are a good coder.

//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js

(adsbygoogle = window.adsbygoogle || []).push({});

Now Google has decided and choose the full responsive viewport method for you. Recently Google Webmasters released a update that has a feature call ‘Mobile Usability’. In this section you can see any mobile performance errors on your website, which I have not been indexed for yet but I read the learn more link instead. In this they specify on what they will mark you on for mobile devices, as they want to give to the user the best website that not only has the best content, but is also the best to view. If you have the best information in front of you and can’t read it then the information become rubbish. For this reason you will have to go down the same method they have chosen.

Even though I have used the fixed viewport method for this website and some others, I believe Google is correct. They are looking to give the user a website that is user friendly and accessible. If you set the viewport at 767px and view it on a iPhone 6 plus, then the button will be for example 20px. If you view that same website on a iPhone 5 with a smaller screen, then that 20px button will be relative in size to 767px and so will be about 10px. This button is now not very user friendly. I think the other method is the quick fix way, but not the best way.

It does make me question why can you set the viewport to a fixed width then? What application would this be useful in?

Google’s New Rules