Is it possible to use css like media queries in javascript? - javascript

I am wondering if there is a way to use media queries in javascript like i use it in CSS ?
i want to handle device-width or orientation and fire a function .
now i am using this code :
window.onresize = function(event) {
/* test for various sizes */
};
but it is no good for me , i don't know how to make it work .
i need it to work in latest chrome without third parity libraries , i'm not sure if it is possible .

I would suggest using window.matchMedia method , wich allows you to test for a particular media query and add an event listener whenever it's matched or not .
Example :
var mq = window.matchMedia("(max-width: 600px)");
mq.addListener(function(event){
if (event.matches) {
console.log("Small Screen mode !");
}
});
Example 2:
onOrientationChange = function(event){
if (event.matches) {
console.log("Portrait mode!");
}
};
var mq = window.matchMedia("(orientation: portrait)");
mq.addListener(onOrientationChange);
/* ... /*
/* When you no longer need to receive notifications , you can remove the listener */
mq.removeListener(onOrientationChange);
This API is supported in : Chrome 9+ , Firefox 6+ , IE10+
Additional info on MDN

Check out Responsive JavaScript. Sounds like it will do what you're looking for.

Try to use matchMedia (jQuery)
// media query event handler
if (matchMedia) {
var mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
// window width is at least 500px
}
else {
// window width is less than 500px
}
}

Related

matchMedia doesnt work unless window is resized

I'm trying to use the window.matchMedia event listener to detect if the user is on a touch device or not. But im just seems to be only activate when the chrome DevTools window is resized, and not actually detect if it is a touch device (for example, on my pixel 3a).
here is the code i used for the event listener
if (matchMedia) {
let mql = window.matchMedia('(pointer: fine)');
mql.addListener(touchChange)
}
and the function which it runs
function touchChange (event) {
if (event.matches) {
touchcontrols = true;
console.log("Touch Controls");
console.log(window.innerWidth);
document.getElementById("lives").innerHTML = "Touch Events!";
}
}
If you just want to see if it matches once you can use:
let matches = window.matchMedia('(pointer: fine)').matches;
window.matchMedia returns an object with a matches property which indicates if it's currently matching your query and an addListener to register a callback which will be called in response to the media query status changing.
More on this: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener

Dynamically detect if position:sticky is supported by the browser

Is there a way to detect, using Javascript or jQuery, whether the browser supports position:sticky or not?
I know most modern browsers support it, but some older browsers and some mobile browsers don't.
I'm not interested in a polyfill. I want to take certain actions only if position:sticky works, otherwise just leave things as they are.
A great and powerful way to check if a CSS feature is available is to use the CSS.supports JavaScript function:
if (CSS && CSS.supports && CSS.supports("position", "sticky")) {
// awesome: position:sticky is supported on this browser!
} else {
// fallback: I cannot rely on position:sticky!
}
I hope this answers your question, but I think it's worth mentioning that if you're tempted to use CSS.supports() you should at least consider responding to a lack of feature just using CSS alone. While JavaScript is a great way to make dynamic changes to a page, you often don't need it to have your page respond to a lack of a feature. This is especially for CSS features like sticky.
E.g.
/*
...
Basic styles for old browsers that don't support sticky go here.
...
*/
#supports (position:sticky) {
/* Overrides to the above styles for modern "sticky" browsers go here */
}
And even then, you often don't even need to go this fancy. For example, let's say you have a nav bar that you would like to be position:sticky if possible, but otherwise just position:absolute. Even though some browsers don't understand sticky, you can say:
.my-nav-bar {
/* The fallback goes first */
position: absolute;
/* This 'enhancement' is ignored if not understood, */
/* but overrides the previous value if the browser supports it. */
position: sticky;
top: 50px;
/* ... etc ... */
}
From modernizr:
/*!
{
"name": "CSS position: sticky",
"property": "csspositionsticky",
"tags": ["css"],
"builderAliases": ["css_positionsticky"],
"notes": [{
"name": "Chrome bug report",
"href":"https://bugs.chromium.org/p/chromium/issues/detail?id=322972"
}],
"warnings": ["using position:sticky on anything but top aligned elements is buggy in Chrome < 37 and iOS <=7+"]
}
!*/
define(['Modernizr', 'createElement', 'prefixes'], function(Modernizr, createElement, prefixes) {
// Sticky positioning - constrains an element to be positioned inside the
// intersection of its container box, and the viewport.
Modernizr.addTest('csspositionsticky', function() {
var prop = 'position:';
var value = 'sticky';
var el = createElement('a');
var mStyle = el.style;
mStyle.cssText = prop + prefixes.join(value + ';' + prop).slice(0, -prop.length);
return mStyle.position.indexOf(value) !== -1;
});
});
Source: https://github.com/Modernizr/Modernizr/blob/master/feature-detects/css/positionsticky.js
with:
prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
Source: https://github.com/Modernizr/Modernizr/blob/master/src/prefixes.js
Working example (w/o Modernizr dependencies):
function browserSupportsPositionSticky() {
var prop = 'position:';
var value = 'sticky';
var prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
var el = document.createElement('a');
var mStyle = el.style;
mStyle.cssText = prop + prefixes.join(value + ';' + prop).slice(0, - prop.length);
return mStyle.position.indexOf(value) !== -1;
};
console.log(browserSupportsPositionSticky());

What is a proper way to detect the support of css "flex-box" and "flex-wrap"?

I'm looking for a solution how we can detect the support of css flex-box and flex-wrap by JavaScript.
I'm aware of modernizr which can do the job but my client does not allow us to load any scripts inside the head section, unfortunately this does not work when loading in the footer.
What is a proper way to achieve this detection on all kind of browsers / devices?
how we can detect the support of css flex-box and flex-wrap by
JavaScript.
Create an element and check the style property. If it is supported, it will return nothing i.e. '' else it will return undefined.
For example, if you run the below snippet in Chrome you will get undefined for columns and '' for flex-wrap.
Snippet:
console.log('flex = ' + document.createElement("p").style.flex);
console.log('columns = ' + document.createElement("p").style.columns);
console.log('flex-wrap = ' + document.createElement("p").style.flexWrap);
Although you have mentioned only Javascript in your question, but there is a CSS way of feature detection as well.
The #supports rule, also called CSS Feature Queries.
You provide the CSS declaration as the condition and the browser will execute that to return whether it supports or not. For example, the following CSS will apply green background color if flex is supported.
#supports (display: flex) {
div { background-color: #0f0; }
}
The browser support is good amongst all modern browsers, barring IE (as usual). For IE and (Safari < 9), you will need to keep a fallback option when #supports rule fails.
Combining the above two, there is an API around that as well which you can use in Javascript to do feature detection.
var isColumnSupported = CSS.supports('columns', '');
console.log('columns supported: ' + isColumnSupported);
var isFlexWrapSupported = CSS.supports('flex-wrap', 'wrap');
console.log('flex-wrap supported: ' + isFlexWrapSupported);
Since CSS.supports() is not supported on IE
This robust method can test any property:value support:
var cssPropertySupported = (function(){
var mem = {}; // save test results for efficient future calls with same parameters
return function cssPropertySupported(prop, values) {
if( mem[prop+values] )
return mem[prop+values];
var element = document.createElement('p'),
index = values.length,
name,
result = false;
try {
while (index--) {
name = values[index];
element.style.display = name;
if (element.style.display === name){
result = true;
break;
}
}
}
catch (pError) {}
mem[prop+values] = result;
return result;
}
})();
///////// TEST: ////////////////////
console.log(
cssPropertySupported('display', ['-ms-flexbox', '-webkit-box', 'flex'])
)
You manually need to provide the test function all the possible property names since the code cannot guess (too many possibilities). This keeps the test code slim instead of it have all possible property names already within it.

How to generically test if mediaqueries are supported?

May sound odd, but I'm looking for a simple way to test if any mediaqueries are supported on a browser.
I know there is respondjs, which comes with a window.matchMedia polyfill, but even using it, I still have to query specific queries like:
window.matchMedia("all and (min-width: 400px"));
which returns an obj.matches = true/false.
What I'm looking for is a generic way to test, "if mediaQueries are supported", yes or no.
I'm currently using:
window.matchMedia("screen and (orienation:landscape),
screen and (orientation:portrait)");
but I don't really like this way of testing.
I also tried:
window.matchMedia("all");
but this (of course) returns true in IE8 when using the matchMedia polyfill. Also, I can't test for matchMedia itself, because I would miss out on a lot of browsers that support media queries, but not window.matchMedia (caniuse).
Question:
Is there a nice and simple way to test for media query support? If possible, I would not want to use window.matchMedia at all to do that.
EDIT:
I also checked Modernizr, which also tests for a specific mediaQuery condition (mq):
testMediaQuery = function( mq ) {
var matchMedia = window.matchMedia || window.msMatchMedia;
if ( matchMedia ) {
return matchMedia(mq).matches;
}
var bool;
injectElementWithStyles('#media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
bool = (window.getComputedStyle ?
getComputedStyle(node, null) :
node.currentStyle)['position'] == 'absolute';
});
return bool;
},
So no generic test, if mediaQueries are supported.
U can choose this option in modernizr
http://modernizr.com/download/

mediaMatch in Android? (Phonegap orientation)

I'm struggling with orientation changed in Phonegap. My plan was to change CSS file when the orientation changed (maybe thats a convoluted way of doing it anyway), but I'm struggling to get any orietation dependant events to happen. I'm currently using the code:
window.onorientationchange = function() {
navigator.notification.alert(
'orientation change!', // message
'Portrait', // title
'buttton'); // buttonName
if (window.matchMedia("(orientation: portrait)").matches){
navigator.notification.alert(
'now in portrait', // message
'Portrait', // title
'buttton'); // buttonName
}
else{
alert("landscape")
}
}
The first alert (whenever orientation changes) is fine, but the second (when it specifically changes into landscape) isn't happening. I'm on Android version 2.3.5. (this method was suggested by Razvan on this question)
You need to setup a listener on the MediaQueryList object. See below for example.
There are ways other than media queries to retrieve device orientation change. Search "mdn orientationchange" for examples.
Create MediaQueryList object, 'orientation'. Contains add/removeListener, media and matches.
Create listener, 'orientationListener'. Tests for media query match.
Get the initial orientation value
Listen for any change to occur
var orientation = window.matchMedia("(orientation: portrait)"),
orientationListener = function(mql) {
if (mql.matches) {
// Media query does match orientation portrait
} else {
// Media query does not match which should mean orientation is now landscape
}
};
// Gets initial match
orientationListener(orientation);
// Listens for change
orientation.addListener(orientationListener);

Categories