Retina Devices in web developing: Do I still need to have 2x images? - html

A lot of the information about Retina devices comes from ~2013 but not much recently.
It seems like, for example in retina.js, it includes anything with a device pixel ratio of > 1.5 to be "retina", but don't all smartphones have well over 1.5 these days? My desktop computer does as well.
My question then, why not just always serve the highest possible resolution images you have access to instead of creating the half-sized versions for "non-retina" devices, which as far as I know don't really exist much and won't suffer much from being served a higher resolution image.
Thanks!!!

Using 2x images is a huge pain.
Who can know what is "best," but I'm currently working with images in a combo like this:
I use a parent element so that the image will fill it - and that parent/or it's ancestors will determine any limits. You can use the picture element. (usually, the src are supplied by a CMS or something {{image.small.url}} etc.
The official answer to your questions would be, that people don't serve the higher res file to everything - because the file is bigger and they want the site to load as fast as possible. / but if you double the images size (twice as big as it will ever be presented, and compress to ~40 or so) then use the parent element to size it - it's actually a smaller file size. There are very specific studies on this. I don't know how that works for painting and browser rendering, though.
MARKUP
<figure class='poster'>
<img src='' alt=''
data-small='http://placehold.it/600'
data-medium='http://placehold.it/1000'
data-large='http://placehold.it/2000'
/>
</figure>
STYLES (stylus)
figure // just imagine the brackets if you want
margin: 0
img
display: block
width: 100%
height: auto
.poster
max-width: 400px
SCRIPT
$(document).on('ready', function() {
// $global
var $window = $(window);
var windowWidth;
var windowHeight;
function getWindowDimentions() {
windowWidth = $window.width();
windowHeight = $window.height();
}
function setResponsibleImageSrc(imageAncestorElement, container) {
var large = false; // innocent until proven guilty
var medium = false; // "
var context;
if ( !container ) {
context = windowWidth;
} else {
context = $(container).outerWidth();
}
var large = context > 900;
var medium = context > 550;
$(imageAncestorElement).each( function() {
var $this = $(this).find('img');
var src = {};
src.small = $this.data('small');
src.medium = $this.data('medium');
src.large = $this.data('large');
if ( large ) {
$this.attr('src', src.large);
} else if ( medium ) {
$this.attr('src', src.medium);
} else {
$this.attr('src', src.small);
}
});
};
$window.on('resize', function() { // this should jog a bit
getWindowDimentions();
setResponsibleImageSrc('.poster', 'body');
}).trigger('resize');
});
It all depends on what you are doing - and there is no silver bullet yet. The context for each image is so unique. My goal is to get in the ballpark for each size - keep the images compressed to 40 in Photoshop on export... double the size they should be, and then the parent squishes them for retina. The size is actually smaller in most cases.
CodePen example: http://codepen.io/sheriffderek/pen/bqpPra

Related

How do I guarantee the v-main to appear more than 70% height of viewport in Vuetify?

I'm pretty new to Vuetify, so please understand. What I've figured out is - <v-main> automatically fills(stretches itself to) the whole empty spaces between <v-app-bar> and <v-footer> in order to take the whole viewport size(height).
What I actually concerned about is when <v-footer> gets too big. it will corrode too many viewport heights so that it may occur <v-main> to be too small. so I made a logic like below to guarantee my <v-main> size to be at least 70% of the height size of the viewport(no matter how/when I resize the browser or which browser, which device I use):
<template>
<v-main v-resize="fn_guarantee_container_min_height">
....
</template>
......
methods: {
fn_guarantee_container_min_height() {
// comp_container : select the background image inside of <v-main>.
// I know it's not that good way but I couldn't help as needed.
const comp_container = document.querySelector("#main--bg");
const num_height__container = comp_container.scrollHeight;
const num_height__container__estimated = window.innerHeight * 0.7;
if(num_height__container < num_height__container__estimated)
comp_container.style = `min-height: ${num_height__container__estimated}px`;
else
comp_container.style = undefined;
},
},
mounted() {
this.fn_guarantee_container_min_height();
},
But hey, as you know, v-main stretches itself to fill enough blank spaces to make the whole component fits to the height of the viewport(100vh). so the logic above occurs such a lagging effect(stretching and shrinking itself) which is absolutely not intended. How may I achieve my goal? I need a silver bullet! Thank you.
I've already tried debouncing and throttling, But as I had expected, It didn't bore any impressive result.
#lee can you just add a class to v-main and with css add min-height: 70vh;?
ie
<v-main class="v-main-container">
.....
<style lang="scss" scoped>
.v-main-container {
min-height: 70vh;
}
</style>

Bootstrap - match vertical column heights that are not in a row

I've a rather complicated website design I'm working on. I have the following 4 containers (I call them that, but they don't have the .container class)
In a wide screen layout:
In a narrow screen layout:
The issue I'm having is matching the total height of the white, grey and yellow containers with the blue container on a wide screen layout:
The grey and yellow containers are in a .row div, so adding the style { display: inline-flex } makes them the same height on a narrow screen layout:
However, this moves them completely to the side in the wide screen layout and this wouldn't match the combined white, grey and yellow containers with the blue container:
I tried a JavaScript solution as #Paulie_D recommended.
$(window).load(function () {
NormalizeHeights();
});
window.onresize = function (event) {
NormalizeHeights();
}
function NormalizeHeights() {
if (window.innerWidth >= 768) {
var carousel = $(".carousel-container");
var dashTop = $(".dash-row-top");
var panelLeft = $(".dash-row-bottom .panel-lightgray");
var panelRight = $(".dash-row-bottom .panel-yellow");
var carouselHeight = parseFloat(carousel.css('height'));
var dashTopHeight = parseFloat(dashTop.css('height'));
var panelLeftHeight = parseFloat(panelLeft.css('height'));
var panelRightHeight = parseFloat(panelRight.css('height'));
var dashBottomHeight;
if (panelLeftHeight > panelRightHeight) {
dashBottomHeight = panelLeftHeight;
}
else {
dashBottomHeight = panelRightHeight;
}
if (carouselHeight > (dashTopHeight + dashBottomHeight)) {
var difference = carouselHeight - (dashTopHeight + dashBottomHeight);
panelLeft.css("height", (dashBottomHeight + difference));
panelRight.css("height", (dashBottomHeight + difference));
}
else {
var difference = (dashTopHeight + dashBottomHeight) - carouselHeight;
carousel.css("height", (carouselHeight + difference));
panelLeft.css("height", (dashBottomHeight));
panelRight.css("height", (dashBottomHeight));
}
}
}
This works, sort off, but it's extremely unlikable in my estimation.
I had a similar problem and the solution I found was rather ugly but worked for me.
I used divs that would clear formats BUT would their presence would be conditioned (using ng-if). Programmatically, I measured the width of the screen and set a threshold. If the width was above the threshold, I set the location of the divs, measured the height of the contents and, when applicable, forcefully changed the height of all the relevant divs to look the same (note that you would need to set this size update AFTER A TIMER is fired to let the rendering to complete).
Hope this gives you some ideas and remember: I was the first to call this ugly.

Reduce the size of text in angularjs when line breaks?

I have a responsive app for desktop and mobile.
In the app i have a div which randomly shows texts of all kinds of lengths.
I want to do the following:
If the line breaks because the length of the text is too wide for the width of that div, i want the font-size to reduce itself (I am using em's in my app).
Is it something i need to build directive for it? is it something that was built and used wildly?
Writing a robust solution for this problem is going to be non-trivial. As far as I know, there's no way to tell whether a line of text breaks. However, we do know the criteria for line breaking is the width of the text being wider than the element, accounting for padding.
The Canvas API has a method called measureText which can be used to measure a string, using a given context with a font and size set. If you spoof the settings of the element with a canvas, then you can measure the text with the canvas and adjust the size until it fits without overflowing.
I've written up a rough implementation of the way I would tackle this.
function TextScaler(element) {
var canvas = document.createElement('canvas'),
context = canvas.getContext('2d');
var scaler = {};
scaler.copyProps = function() {
var style = element.style.fontStyle,
family = element.style.fontFamily,
size = element.style.fontSize,
weight = element.style.fontWeight,
variant = element.style.fontVariant;
context.font = [style, variant, weight, size, family].join(' ');
};
scaler.measure = function(text) {
text = text || element.innerText;
return context.measureText(text);
};
scaler.overflows = function() {
var style = window.getComputedStyle(element),
paddingLeft = style['padding-left'],
paddingRight = style['padding-right'],
width = style.width - paddingLeft - paddingRight;
return scaler.measure() > width;
};
scaler.decrease = function() {
// decrease font size by however much
};
scaler.auto = function(retries) {
retries = retries || 10;
if(retries <= 0) {
scaler.apply();
console.log('used all retries');
}
if(scaler.overflows()) {
scaler.decrease();
scaler.auto(retries - 1);
} else {
console.log('text fits');
scaler.apply();
}
};
scaler.apply = function() {
// copy the properties from the context
// back to the element
};
return scaler;
}
After you've sorted out some of the blank details there, you'd be able to use the function something like this:
var element = document.getElementById('');
var scaler = TextScaler(element);
scaler.auto();
If it doesn't manage to decrease it within 10 retries, it will stop there. You could also do this manually.
while(scaler.overflows()) {
scaler.decrease();
}
scaler.apply();
You'd probably want some fairly fine tuned logic for handling the decrease function. It might be easiest to convert the ems to pixels, then work purely with integers.
This API could quite trivially be wrapped up as a directive, if you want to use this with Angular. I'd probably tackle this with two attribute directives.
<div text-scale retries="10">Hello world</div>
Of course, if it's not important that all the text is there onscreen, then you can just use the text-overflow: ellipsis CSS property.

Loader content cannot be displayed in custom resolution

I am trying to make a custom full screen mode for my media player. It basically assigns content to resized movie clip and displays. However when comes to particular contents it is unable to show in full screen mode. Actually there is no problem in default but only in FS. Here is the code that activates FS Mode.
function FSMode(e:MouseEvent):void
{
fullScreenToolbar = new ExitFSClass();//this exits full screen
_coordinate.x = contentLdr.content.x;
_coordinate.y = contentLdr.content.y;
_width = contentLdr.content.width;
_height = contentLdr.content.height;
contentLdr.content.x = -250;
contentLdr.content.y = -135;
this.setChildIndex(contentLdr, this.numChildren - 1);
if(contentTypArr[currentCategory] === "animation")
{
addChild(fullScreenToolbar);
this.setChildIndex(fullScreenToolbar, this.numChildren - 1);
if(Capabilities.screenResolutionX >= 1920)
{
contentLdr.content.width = 1800;
contentLdr.content.height = 1012.5;
}
else
{
contentLdr.content.width = Capabilities.screenResolutionX;
contentLdr.content.height = Capabilities.screenResolutionY;
}
fullScreenToolbar.x = 0;
fullScreenToolbar.y = 965;
fullScreenToolbar.width = contentLdr.content.width;
fullScreenToolbar.addEventListener(MouseEvent.CLICK, openToolbar);
fullScreenToolbar.buttonMode = true;
}
}
Why some contents cannot be displayed? I am unable to see related problem or conflict with code.
Basically the Loader content resolution is different (greater in this situation) than the displaying area. There are overflowing parts that makes fs not working properly. Fixing the content resolution makes no problem and the function operates well.

Calculate size of SVG element in HTML page

How can I reliably ask for the size (in pixels) an SVG element is taking up on the host page?
Both svg.offsetWidth and svg.getBoundingClientRect().width work in Chrome v34.
Neither of those work correctly in Firefox v29. (The former is empty, the latter returns incorrect values.)
Test Page: http://jsfiddle.net/dL5pZ/3/
The motivation for this question is to get a reliable implementation for this answer, which requires knowing the aspect ratio of the outside of the element. Further, for this question I need to know the actual size of the SVG, or at least something that returns proportionate values across different calls and a resizing element.
I've been down that road before. Unfortunately, most of the functions for getting the size of the <svg> element are buggy in Firefox. The only working solution I found was using window.getComputedStyle(svgElement).width (or height), which needs to be parsed (and also only works when svgElement.display == 'block', which it is in your example).
I have adopted your fiddle to work in Firefox: http://jsfiddle.net/dL5pZ/5/
Update: The issue with display 'inline' was fixed some time ago around Firefox 29.
Update 2: As mentioned in another answer, getBoundingClientRect should also work nowadays.
Some more info from my research because I've spent the last 2 days working on this issue..
So, it always works in Chrome and Opera, it works in IE if you add preserveAspectRatio="xMinYMin slice" but Firefox seems buggy.
To make it work cross platform try:
a) accessing width and height of SVG directly - Ch,O,IE
b) getComputedStyle:
var style = window.getComputedStyle(svg, null);
var svgWidth = style.getPropertyValue("width").slice(0, -2); // "1240px" -> "1240"
keep in mind that for single queries it is fine, but when you try to do it about 60 times per second then the browser becomes very slow
c) as we know this issue happens when we have
<div><svg style="width:100%; height:100%"></svg></div>
and the width and height of SVG element are 1 in Firefox.. but these dimensions are as same as the dimensions of the div parent element which you can access! But to make life harder it doesn't work in IE.
So reassuming, this is my final cross browser code:
if(!svg.width.baseVal.value || svg.width.baseVal.value < 2){
//this is the FF case
if(!this.parentElement) return;
this.width = this.parentElement.clientWidth;
this.height = this.parentNode.clientHeight;
}
else{
//this works for Ch,O,IE
this.width = svg.width.baseVal.value;
this.height = svg.height.baseVal.value
}
getBoundingClientRect has been fixed in Firefox from version 33 onwards and will do what you want it to now. See bug 530985 for details.
This was the way I fixed it:
var heightComponents = ['height', 'paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth'],
widthComponents = ['width', 'paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'];
var svgCalculateSize = function (el) {
var gCS = window.getComputedStyle(el), // using gCS because IE8- has no support for svg anyway
bounds = {
width: 0,
height: 0
};
heightComponents.forEach(function (css) {
bounds.height += parseFloat(gCS[css]);
});
widthComponents.forEach(function (css) {
bounds.width += parseFloat(gCS[css]);
});
return bounds;
};
Using your jsFiddle: http://jsfiddle.net/dL5pZ/7/
This is what I ended up using:
var svgWidth = svg.clientWidth || window.getComputedStyle(svg).width.slice(0, -2),
svgHeight = svg.clientHeight || window.getComputedStyle(svg).height.slice(0, -2);
as clientWidth and clientHeight always return 0 in Firefox.
For d3 users:
var svg = d3.select('#yoursvg')[0][0],
svgWidth = svg.clientWidth || window.getComputedStyle(svg).width.slice(0, -2),
svgHeight = svg.clientHeight || window.getComputedStyle(svg).height.slice(0, -2);
Hope it helps.
<button onclick="demosvg()">click on</button>
<svg>
//<image xlink:href="demo.jpg" id="img1" height="200" width="200"/>
<img id="myImg" src="demo.jpg" style="width:500px;height:98px;">
</svg>
<div id="demo"></div>
<script>
function demosvg() {
var var1 = document.getElementById("img1").naturalWidth;
document.getElementById("demo").innerHTML = "width is: " + var1+ " pixels";
}
</script>