I need to know how the CSS media query works.
I mean, if I use #media(min-width: 768px), does this function called every time the window is resized ?
Because I am wondering if I can use a Javascript $(window).bind('resize orientationchange') or if it is more resource intensive.
It is for add or remove a class to a div, an exemple :
http://jsfiddle.net/xbh28o08/
My goal is to enter in the HTML a data attribut which determine when the navbar has to collapse (data-breakpoint"768" for example). And I would get this breakpoint for make a responsive navbar automatically, without change any CSS. My idea was to do it with Javascript but it seems really not a good idea according to your answers
var widthScreen = $(window).width();
if (widthScreen > 768)
$('nav').addClass('large');
else
$('nav').addClass('small');
$(window).bind('resize orientationchange', function() {
widthScreen = $(window).width();
if (widthScreen > 768){
$('nav').addClass('large');
$('nav').removeClass('small');
}
else{
$('nav').removeClass('large');
$('nav').addClass('small');
}
});
to answer your first question: yes a media query does get called every time you do resize the window.
there is no need to add classes with javascript, I provided you with an example:
it does completely the same but no js needed. Its better to avoid using javascript when its not needed.
nav{
background: green;
}
#media(min-width: 768px){
nav{
background: red;
}
}
<nav>
<ul>
<li>Link 1</li>
<li>Link 2</li>
</ul>
</nav>
I suggest you use css media queries instead of javascript as css is faster than javascript
As soon as Your device width is 768px all the css in that will be called and would overwrite the any other if exist
For more info you can check the link below
Css Media Queries
A CSS media query will apply whenever the conditions in it are fulfilled (for instance, media screen and max-width of 768px), and be ignored whenever it is not. It applies to the window size and will update on resize. You can test this on this website by shrinking your browser.
Such a use-case (using the window resize event) is not recommended as it will trigger on every resize event. Not just when the resizing is finished, but also every tick between start and end. The only use case I know of is to add/remove classes, which is both not recommended, and also a downright CPU hog.
Media query will trigger only when particular point (width or height) mentioned in your media query, whereas javascript resize will trigger at every pixel changed during resize. And, JS is more resource intensive IMO whereas CSS is not and faster. Have a read here
So, in your case, instead of removing and adding classes, have one class and override it's properties based on the screen size in your media query. Something like:
.my-class { width: 400px; }
#media(min-width: 768px){
.my-class { width: 200px; }
}
OR
You can have 2 classes all the time, but only one will take effect based on the screen size. This way you don't override properties (which is a bit ugly, but, that's just me)
// screen <= 767
#media(max-width: 767px){
.nav-small {
width: 320px;
}
}
// screen >= 768
#media(min-width: 768px){
.nav-large {
width: 100%;
}
}
Related
I have a nav bar that I want to call either one of 2 options when clicked according to screen size.
I have tried various options including media queries and javascript but I think my construction of the queries is letting me down.
I need to do this:
if screen size <960 then
<li>Page</li>
else
<li>Page</li>
end```
is there a way to do this?
thank you
As the other commenter said, you can use media queries for this. One very easy to understand solution would look like this:
Solution A: Media Queries
<html>
<style>
/* We are disabling linkA from being displayed and allowing linkB to be displayed normally */
#linkA {
display: none;
}
#linkB {
display: inherit;
}
/* if screen width <= 960px, we will display linkA and hide linkB */
#media screen and (max-width: 960px) {
#linkA {
display: inherit;
}
#linkB {
display: none;
}
}
</style>
<body>
<ul>
<!-- Notice the ID tags -->
<li id="linkA">Page</li>
<li id="linkB">Page</li>
</ul>
</body>
</html>
The media query redefines CSS attributes if the query matches. In your case if the screen width is less or equal 960px.
Solution B: Javascript
Another solution for your problem would be to call a javascript function when the link is clicked like this:
<span onclick="buildLink()">Page</span>
Note: I did replace a with span since if there is no href there is no reason to use a
In the javascript you could dynamically change num_months by dividing the width with by the amount of pixels you need to display a month:
function buildLink() {
const link = "page/index.php?lang=en&id_item=2&num_months=";
// casting to integer is very important, since we get decimal values otherwise
const num_months = parseInt(window.innerWidth / 480)
// window.location.href basically sets the address bar of the browser
window.location.href = link + num_months
}
I hope I have given you a clear answer on your question and some room to think about other possible solutions.
Also: You seem to be new to web development so welcome onboard and enjoy the bumpy ride :)
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>
I need to call a function when a window is resized below the 400px breakpoint. The obvious solution to handle this would be to watch the window.resize() event like this:
Window.Resize Solution
script:
$(window).resize(function(){
if($(window).width() < 400)
console.log("trigger");
});
Window.resize Fiddle
However this triggers continuously as the resize happens, this can result in hundreds of calls on this function, and will trigger at unncessary times like resizing from 300px to 200px;
While trying to find a way to avoid this I came up with a solution using CSS media queries:
CSS Media Query Solution
script:
$(".foo").on('transitionend', function () {
console.log("trigger")
});
css:
.foo
{
width: 0;
height: 0;
color: white;
transition: 0.1s;
}
#media screen and (max-width: 400px) {
.foo {
color: gray;
}
}
CSS Media Query Fiddle
The idea here is that the CSS watches for the window to resize to 400px then applies an arbitrary transition to an invisible element. Once done, the transitionend event is fired and the listener calls on my function. This only happens once when the screen goes below 400px and once when it goes back above.
Now of course there are pitfalls to this solution:
IE8/IE9 don't support transitionend
You must create an unnecessary element for each resize event you want to watch
The code is inherently more confusing as it is a "hacky" technique.
But other than those downfalls I was wondering if this method would be more efficient/better use if you want to avoid the continuous calls. Or is the underlying implementation of media queries doing more work than the resize event would anyway.
I think your main complication is splitting the code over so many places. Yes, CSS is nice and all, but now your code is reliant on two places! The easiest way to sort this is to simply store your value in JS:
var isSmall = false;
$(window).resize(function(){
if(
(window.innerWidth < 400 && !isSmall) ||
(window.innerWidth > 400 && isSmall)
){
console.log('we have passed the treshold!');
isSmall = !isSmall;
}
}).resize();
I guess using the CSS transitionend would work, but it seems so cumbersome to keep in sync.
I need javascript #help.
I have an object(#objID) with three different data state (A B & C) (https://www.dropbox.com/s/zn19k87eu2hp8ow/data-states.jpg?dl=0)... Each state contain some css to describe the look of it..
I want to use javascript to detect media queries change and add the appropriate data state to #objID.
(ie.
if screen is under 320px then add [data-state="A"] to #objID
or if screen is between 320px and 728px then switch to [data-state="B"]
or if screen is above 1024px then switch to [data-state="C"]
)
similar to this concept..http://zerosixthree.se/detecting-media-queries-with-javascript/
but im not sure how to implement it.
Please help. Thanks
To simplify you can do something like this:
window.matchMedia("(max-width: 320px)").addListener(function() {
// Change the value of `data-state`
});
window.matchMedia("(min-width: 321px) and (max-width: 728px)").addListener(function() {
// Change the value of `data-state`
});
However you need make sure the browser supports window.matchMedia and also handles maintaining state etc to know when you've crossed from one breakpoint and into the other and identify which is active as both will trigger as you exit and enter breakpoints.
As for doing it on window.onresize this is not a very performant way to do this and you must throttle/debounce if you do it that way. Using matchMedia will only trigger when the breakpoint changes rather than continuously on resize. It also give you the benefit of keeping your CSS media breakpoints in sync with your JS.
This is a Polyfill for browsers which do not support it as mentioned and this guide might also help you.
However:
I have an object(#objID) with three different data state (A B & C).
Each state contain some css to describe the look of it..
Sounds as though you want to change the CSS styles applied to an element based on the data-state attribute, which you are going to change per breakpoint?
Correct me if I am wrong but why can't you just use media queries to change the CSS that is applied to it instead?
#media only screen and (max-width: 320px) {
/* State A */
.css-selector {
color: red;
}
}
#media only screen and (min-width: 321px) and (max-width: 728px) {
/* State B */
.css-selector {
color: green;
}
}
#media only screen and (min-width: 728px) {
/* State C */
.css-selector {
color: blue;
}
}
You need the onresize event
window.onresize = function(event) {
//...
};
The screen has two dimensions, width and height, and you describe a one-dimensional comparison, which does not give us enough information about what you want to achieve. Anyway, you can use window.innerWidth and window.innerHeight inside your onresize event.
I have a div which has a basic width value, set in a css file.
In that file, i also have a media query for a new basic width, upon orientation change to portrait.
in my javaScript i have a function updating the width dynamically when document is ready.
What happens is, that when the media query is called, the updated width - is the width which was set dynamically by the js, and it's automatically overwrites the new media query css width.
In other words, once I dynamically set the width in the code - the media query will no longer take any effect.
how can i make the media query css width overwrite the current width (which was set dynamically by js?)
THANK YOU!
HTML + JS :
<html>
<head>
<script>
var defaultNumOfItem = 3;
$(document).ready(function()
{
updateWidth(4);
});
function updateWidth(currentNumOfItems) {
var basicWidthText = $('#list').css('width');
var basicWidth = parseFloat(basicWidthText .slice(0, basicWidthText .indexOf('px')));
$('#list').css('width', basicWidth * currentNumOfItems/ defaultNumOfItem);
}
$(window).bind('orientationchange, function(){
updateWidth(4);
});
</script>
</head>
<body>
<div id='list'>
</div>
</body>
</html>
CSS:
#list {
width: 900px;
}
#media only screen and (orientation: portrait){
#list {
width: 600px;
}
}
P.S the use of !important did not work for me, since if i put it in the css - the js will take no effect. and if i put it in the js - the media query takes no effect - same will happen by putting it in both the js and the css
This can probably be achieved without JavaScript, though the full intent of the code is not totally clear, so this is how to do it while maintaining the current functionality.
#media only screen and (orientation: portrait) {
#list {
max-width: 600px;
}
}
The max-width CSS property trumps width, even if width is defined inline, externally, or made !important. The same is true of the min-width property under different circumstances.
Just give it a try !important
#media only screen and (orientation: portrait){
#list {
width: 600px !important;
}
}
If I understand this correctly you want to use the media query only if orientation is portrait and the js if the orientation is landscape. In this case you can try this:
$(window).bind('orientationchange', function(event){
if(event.orientation != "portrait")
updateWidth(4);
});
this way the js will not overwrite the width that you wanted to set through the media query in portrait
Ok, found a work around that actually works!
What i do, is simply remove the "width" attribute from the #list every time the orientation changes:
$(window).bind('orientationchange, function(){
$('#list').css('width','');
updateWidth(4);
});
so that way, the external css does take before the js manipulation.