Is transform: scale(x) a costly operation? - javascript

I have a UI element that is designed to work best at exactly '200px' width. But if the size of the UI needs to change based on window / media size, it would be a pain to have to adjust this Component bit by bit and change the width away from 200px.
Is changing the size of a component by using transform: scale(x) to adjust to window / media size an acceptable practice? Is it costly in performance? In practical reality, window / media size will be set from the beginning, so the scale function would only have to be run once anways.
if (screen width < 600px) {
element.style.transform = "scale(.7)"
} else {
element.style.transform = "scale(1)"
}

Is transform: scale(x) a costly operation?
No, the transform operation doesn't require a DOM update. A browser makes a rendering update. Its pros are its performance costs are low, it works fast. Its cons are scaling could greatly downgrade its visual quality (for example, blur images), the downscaled component with its content could be hard to use or read.
A JS usage to set CSS is definitely a costly way to make changes. The most efficient way is to use CSS only (media query).
It looks weird to 'scale' a component for a small screen. A common way to solve it now is to make a responsive layout. But think, you don't need to let its content be dynamic inside. Such a task could be solved with CSS. Just make another step forward. Tie the inner content with outer sizes at CSS - use em/rem units instead of px for all its measures. And the media query will change its base font-size only. Different size, no potential scaling visualization issues, same content position. :)
The CSS could be like this below. Sorry, a minimal working HTML, CSS, JS to demonstrate the concept. To check JS in different screen sizes in this snippet - change your screen size, refresh the snippet. The CSS option works without a refresh.
function setSizeJs() {
const element = document.getElementById('target-element-px');
element.style.transform = window.innerWidth < 600 ? 'scale(.7)' : 'scale(1)';
}
.parent {
font-size: 14px;
}
#target-element-px {
/* original width */
width: 200px;
/* colorize element to show its size */
background-color: green;
}
#target-element-em {
/* main style, will be applied always */
/* an equivalent of 'width 200px' in EMs, where EM is taken as '14px' from the 'parent' class */
width: 14.28571428571429em;
background-color: grey;
}
#media screen and (max-width: 600px) {
/* additional style, will be applied only when the screen size will be less than 600px */
/* it will overwrite the main style */
#target-element-em {
font-size: 0.7em;
}
}
<div class="parent">
<div id="target-element-px" class="target-element" onload="setSizeJs">
Some content for original 200px width
</div>
<div id="target-element-em" class="target-element">
Some content for original 200px width
</div>
</div>

Related

Make sap.m.CustomTile resizable for resolution e.g. from 500px to 320px

I customized the sap.m.CustomTile with some sap.m.FormattedText. I need this CustomTile to be resizable according to display resolution e.g. from 500 px to 320 px. I used for this:
#media only screen and (max-width: 500px) {
.tileSmall.sapMCustomTile {
width: 80.9vw !important;
height: 80.9vw !important;
}
}
#media only screen and (max-width: 320px) {
.tileSmall.sapMCustomTile {
width: 200px !important;
height: 200px !important;
}
}
I can not use % because it behaves strange in my app. So I am trying to use vw instead. I did demo. I would like to keep it all the time as it for resolution 530px in the:
But when the resolution is change to e.g. 417px I got:
The resolution 357px I got:
Is there any way how to anchor footer and subfooter (last two rows)?
Or how to change height of the gap (created by br tag) according to tile height?
Thanks for any advice.
Because you are using VBox inside the custom tile, it is fairly easy to achive what you want. You can check out the Size Adjustments Explored demo for more examples.
The basic idea is that you can play around with the grow / shrink factors of each item inside the VBox. By default, all the items of a VBox are treated equally and are stretched to fill in the available space. Because you want your header and footer to be fixed, you should set the shrinkFactor (default = 1) and growFactor(default = 0) to 0 for these items.
The center of the tile should be just "whitespace" to fill in the rest of the available space, so you can give it growFactor and shrinkFactor equal to 1. You also don't need to put brs in there, because the item will grow / shrink dynamically to fill in the remaining space.
You can add these factors for each UI5 Element using the layoutData aggregation and passing a FlexItemData element.
Another small change is that you should specify width: "100%" and height: "100% for the VBox to make sure its size adjusts based on the tile's size.
Header / footer
new sap.m.FormattedText({
htmlText: "whatever you have now",
layoutData: new sap.m.FlexItemData({
shrinkFactor: 0
})
});
Center
new sap.m.FormattedText({
htmlText: "no need to put anything here",
layoutData: new sap.m.FlexItemData({
shrinkFactor: 1,
growFactor: 1
})
});
You can find a working version of this solution here: http://jsbin.com/tirizanaje/1/edit?html,css,output

Increment negative value of property based on window size

I don't know if this question has an easy or hard answer.
The situation is that I have an element on the page with negative margin:
.element {
margin-left: -195px;
}
It works well with a screen size 1440x532 (check with Chrome's inspector element).
What I want is kind of simple to explain.
I want an increase of 1 pixel (for instance) in the margin-left of the element anytime the window is larger by one pixel:
So, if window size is 1441, the margin-left of the element be -194px. If the window size is 1451, the margin-left of the element be -184px.
In the same way, I want this to work from 1440px upwards.
IMPORTANT NOTE: What I want is a dynamic value for the margin-left that increases based on screen size and not a kind of media query which would make the value always remain the same between an interval of screen sizes. What I want would force me to add a massive number of media queries.
Is this possible with javaScript or jQuery? (or even CSS?)
The Jquery solutions that other users gave you works perfectly for this use, but if you prefere you can also use a CSS-only alternative (it works even if the user has disabled scripts!).
It has got also a good support among browsers
You can implement your CSS in this way:
#element{
margin-left: -195px;
}
#media screen and (min-width: 1440px){
#element{
margin-left: calc(-195px + 100vw - 1440px); //100vw is the width of the screen
}
}
It adds a pixel for each pixel above 1440
Tell me if this is what you mean
This is not possible with CSS since there is no property or method to capture the window size. If there would be, this could be done using calc().
However, this is possible with JavaScript.
function resizeScreen() {
var windowWidth = $(window).width();
var $element = $('.element');
if (windowWidth > 1440) {
// Calculate the new (negative) margin by subtracting the windows width by 1440 (e.g. 1500-1440 = 60). The new margin would be: -195 + 60 = -135.
var newMargin = $element.css('margin-left') + (windowWidth - 1440);
$('.element').css('margin-left', newMargin)
}
}
$(window).resize('resizeScreen');
Yes is it possible with Jquery with resize()
$(window).resize(function() {
if (($(window).width() <= 1441)) {
$('.element').css('margin-left', "-194px")
}else if($(window).width() <= 1451){
$('.element').css('margin-left', "-184px")
}
});
But i suggest to you to use media queries with css:
#media screen and (max-width: 1441px) {
.element {
margin-left: -194px;
}
}
#media screen and (max-width: 1451px) {
.element {
margin-left: -184px;
}
}

Ensure an element retains a specified aspect ratio

Is there anyway to specify an aspect ratio in CSS such as 4:3 or 16:9 and then have the div (container) block fit the current window width and height?
Quite a simple question hopefully it has a relatively simple answer.
Edit: those still interested a great example of achieving this using only styles would be Bootstrap's responsive helpers classes.
For this I fear you'll need some JS. I used jQuery here:
function preserveAspect() {
var scaled = $("#scaled");
scaled.height("100%");
scaled.width("100%");
scaled.css("box-sizing", "border-box");
var ratio = 16/9;
var w = scaled.outerWidth();
var h = scaled.outerHeight();
if (w > ratio*h) {
scaled.width(ratio*h);
// horizontal centering is done using margin:auto in CSS
} else if (h > w/ratio) {
var newHeight = w/ratio;
scaled.height(newHeight);
// for vertical centering:
scaled.css({marginTop: ($("body").height()-newHeight)/2});
}
}
$(document).ready(function() {
preserveAspect();
$(window).resize(preserveAspect);
});
Explanation:
First we scale up our div to 100% in width and height so that we know how much space it has.
Then we look up if it is too wide which means that the width is more
than height times ratio.
If so, change width. Height is at 100% already.
Otherwise it might be too high, in which case we want the scale to be width divided through ratio. To center vertically we use a margin-top set to (window_height - element_height) / 2.
If neither of both rules apply, the div is scaled properly already.
In the end we add event listeners for when document is fully loaded and whenever the window size changes.
Full code and working example here:
http://jsbin.com/efaRuXE/5/
This question's a few weeks old now, but there is a pure CSS way to accomplish this. Thanks to Danield for using it to answer this question. It uses the vw and vh units, like so:
#wrapper {
height:75vw;
max-height:100vh; /* max-height / height = aspect ratio */
width:100vw;
max-width:133.3333vh; /* max-width / width = aspect ratio */
position:absolute;
}
The bad news is that support is iffy in current mobile browsers and in IE before version 11.
Found a way. This may be rough but it should get you going. Set the element's height to zero and then use a percentage for the padding.
jsFiddle example
For example, 4:3:
div {
height: 0;
padding-bottom: 75%;
background: #999;
}
For example, 16:9
div {
height: 0;
padding-bottom: 56%;
background: #999;
}
Unfortunately no.
I've proposed once on www-styles WG # W3C construction like this:
div {
width: 50%;
height: width(56.25%); /* 16:9 ratio */
}
but no one from browser vendors expressed any interest at that moment.
And anyway that solution above allows to define ratio of boxes only. But layout model used by CSS does not allow to define inscribing declaratively.

how to change the font-size proportionally to the change size of the window in CSS3 or javascript

I do some web app and i have some problem with font-size.
How to change the font-size proportionally to the change size of the window in CSS3 or javascript?
The ideal way to do this is using the vw unit, which is defined as 1/100th of the viewport width (hence the name). So, for instance, if you wanted your text to be 4.5% of the browser's width at all times, you could use the size:
font-size: 4.5vw;
… and theoretically, that should work. Unfortunately, you'll find, it doesn't quite work as expected: there's a bug in WebKit browsers (at least) where the value for font size isn't live-updating (although it is for all other dimensions). You need to trigger a repaint in order for the font size to change, which can be done by updating the z-index property from JavaScript:
window.addEventListener('resize', function(){
document.getElementById('myEl').style.zIndex = '1';
}, false);
This may create a little bit of choppiness, but it means you don't have to calculate any actual dimensions in JavaScript, and you don't need to used "stepped" sizes like with media queries.
The ideal way to do so is to combine between the VW font-size and #media queries. Reasons are:
1) em for itself won't rescale by window size
2) vm for itself will be too small for resolutions / screens lower than 800px.
So the right way to achieve this is:
Define a class - prop-text with VM=1.0 for your desired screen width
Add media queries to fit the font-size with your desired lower resolution grids.
For my responsive grid (which sets a 1/2 column to take 100% width below 768px width) it looks like that:
<style>
.prop-text{font-size:1.0vw}
#media (max-width : 768px) {
.prop-text{font-size:2.0vw}
}
/*other media queries here - fit font size to smartphone resolutions */
</style>
<div class="prop-text">your text is here</div>
Set your base font size (the one you define for your body element in css) in px then everywhere in the rest of your page set font sizes relative to that one using emunit, then you can use media queries to change the font sizes of all your pages by just changing your base font, something like this:
body {
font-size: 15px;
}
#media (max-width: 1000px) {
body { font-size: 1.3em; }
}
#media (max-width: 500px) {
body { font-size: 1.1; }
}
You have 3 ways to do it:
Using http://fittextjs.com/, but pages can start to be slower
Using media queries
Using ems
Now, it depends on what you want to be your final result.
I'd go to option no 3.
I think the best way might be vh, beeing that font-size changes the height of the text. Using vh means that the text will always foolow the size of the page, even if the user resizes the page or the screen is small.

How can I change a CSS attribute by Javascript when a certain minimum screen resolution size is detected

I have this code:
function AUTADIV () {
var BRW = window.outerWidth;
x = (BRW/1280) * 20
document.getElementsByTagName("a").style.fontSize = x
}
and the tag <a> is already under this class in a .css file:
a {
position:relative;
z-index:1;
color:White;
background-color: transparent;
font-size:20pt;
text-decoration: none;
text-shadow: blue 0em 0em 0.4em
}
When someone with a larger screen sees my site, the background does fill it all, but the font is too small. Is there any way to make it automatically resize? If not, how can I change font-size:20pt by JavaScript? My code only works if the font-size style is inline, and I need it in the CSS script.
I have found that the code I need activates with the onResize event.
If it needs to be in the CSS then it might be difficult to do. If however, it's able to be changed dynamically with JS then you can accomplish this with a simple test like:
(I'm using jquery)
$.getDocHeight = function(){
return Math.max(
$(document).width(),
$(window).width(),
/* For opera: */
document.documentElement.clientWidth
);
};
if($.getDocHeight>threshhold){ // some threshhold of a max width
$('a').style('font-size','40pt');
}
This can be done in regular js as well. It's hard to determine the width on all different browsers, thats why I included the function. But once you have the width, you just need to do a simple check and you can bump up the font-size style for your anchor tags. I suggest having static sizes so that the font is more predictable and doesn't scale with your page size.
This is a best practice when considering different types of users (like mobile users where you definitely do not want the font to be so small that all of it fits on one page).
Src for code: http://james.padolsey.com/javascript/get-document-height-cross-browser/
You may modify the rules by accessing the CSSRule-Object.
Details:
IE<9 : http://help.dottoro.com/ljcufoej.php
Others: http://help.dottoro.com/ljdxvksd.php
You might get better results using a media query:
#media all and (max-width: 1280px) {
a{font-size:12pt;}
}
You can repeat this for increasingly smaller sizes. It won't smoothly transition, but it doesn't require JavaScript (and besides so much changes when you resize a window that a jump in text size probably won't be noticed).

Categories