Multiple media queries in javascript - javascript

I'm trying to check the screen size with Javascript.
My elements will be animated differently depending on the size of the screen.
I think I am not too far from the result but without really fully understanding it.
When I load the page I have a console.log that appears twice regardless of the size of the window.
By reducing the window manually, by dragging the mouse, there is:
- 2 console.log('MD') when the size for MD is ok
- 1 console.log('SM') when the size for SM is ok
By enlarging the window manually, by dragging the mouse, there is:
- 1 console.log('MD') when the size for MD is ok
- 1 console.log('SM') when the size for LG is ok
- 1 console.log('LG') when the size for LG is ok
But by adjusting the size of the window with the browser icon, my console.log are as I wish.
Would it be possible to have more explanation?
I hope I've made myself clear.
let mqls = [
window.matchMedia('screen and (min-width: 768px) and (max-width: 991px'),
window.matchMedia('screen and (min-width: 992px)')
];
function test(mql){
if( mqls[0].matches ){
console.log('MD')
}
else if( mqls[1].matches ){
console.log('LG')
}
else if( !mqls[0].matches && !mqls[1].matches ){
console.log('SM')
}
}
for ( let i =0; i < mqls.length; i++ ){
test(mqls[i]);
mqls[i].addListener(test);
}

function checkScreen(){
const checkMobile = window.matchMedia('screen and (max-width: 575px)');
const checkTablet = window.matchMedia('screen and (min-width: 576px) and (max-width: 991px)');
const checkDesktop = window.matchMedia('screen and (min-width: 992px)');
checkMobile.addListener(function(e){
if(e.matches) {
console.log('MOBILE');
}
});
checkTablet.addListener(function(e){
if(e.matches) {
console.log('TABLET');
}
});
checkDesktop.addListener(function(e){
if(e.matches) {
console.log('DESKTOP');
}
});
}
checkScreen()
I figure it out but maybe there is better solution ?
EDITED
with the solution above my function doesn't start when my page loads or when refreshing so I have to do this
mobile();
function mobile(){
const mql = window.matchMedia('screen and (max-width: 575px)');
checkMedia(mql);
mql.addListener(checkMedia);
function checkMedia(mql){
if(mql.matches){
console.log('Mobile');
}
}
}
tablet();
function tablet(){
const mql = window.matchMedia('screen and (min-width: 576px) and (max-width: 991px)');
checkMedia(mql);
mql.addListener(checkMedia);
function checkMedia(mql){
if(mql.matches){
console.log('tablet');
}
}
}
desktop();
function desktop(){
const mql = window.matchMedia('screen and (min-width: 992px)');
checkMedia(mql);
mql.addListener(checkMedia);
function checkMedia(mql){
if(mql.matches){
console.log('desktop');
}
}
}
If I put my media queries in an array and use a loop at each refresh as much output in my console as item in my array
There's probably something I don't understand.

Related

Why wont my navbar collapse when on mobile on page load

I'm trying to collapse the navbar when on mobile but the navbar only collapses when i resize the tab manualy. So it probably has something to do with it not checking the size of the screen when starting up the site. I've already tried some stuff with addeventlisteners but i just keep getting errors because op unexpected tokens. my original code was:
function openNav() {
document.getElementById("mySidebar").style.width = "190px";
document.getElementById("main").style.marginLeft = "190px";
}
function closeNav() {
document.getElementById("mySidebar").style.width = "0";
document.getElementById("main").style.marginLeft= "0";
}
var x = window.matchMedia("(max-width: 600px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes
function myFunction(x) {
if (x.matches) { // If media query matches
closeNav()
}
}
after asking some people for help i eventualy started to mess around with this:
var x = window.matchMedia("(max-width: 600px)")
x.addEventListener("change", () => {
myFunction(x);
});
and
window.addEventListener('resize', ()=>{
var x = window.matchMedia("(max-width: 600px)")
if (x.matches) { // If media query matches
closeNav()
}
});
I have been awake for hours and i know it's probably something stupid.
Instead of JavaScript you can use CSS #media-queries like:
#media only screen and (min-width:0px) and (max-width: 767px)
{
'your style here'
}
#media only screen and (min-width:768px) and (max-width: 1024px) and (orientation: portrait)
{
'for tablet portrait view'
}
#media only screen and (min-width:768px) and (max-width: 1024px) and (orientation: landscape)
{
'tablet view landscape'
}
Also please don't forget to add viewport meta tag in your page section.
meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=3"
(keep above meta tag inside < /> )
view port meta tag will read your browser resizing and you can achieve to response web layout, show and hide elements in specific device sizes etc.

JS match.Media with media query range

I am having an issue getting my site to respond to matchMedia query range using media.Match.
Updates based on comments: I need to use match.Media instead of CSS media queries because i need to check if a component is present and if true, i then need to add a class to another element if the browser size is between 1400 - 1800px. Also, i do need this to fire every time the browser is resized.
To troubleshoot, I have tried:
Using a single matchMedia('(min-width: 1400px) and (max-width: 1800px)')
Doing a single match (using only min-width: 1400px) and that succeeds. However, when I add in my 2nd variable 'mq.Max' and 'and statement', the whole thing fails.
I have read through MDN and still not seeing how to implement this.
JS below, thank you for any suggestions you may have.
if (jQuery('.jump-nav').length) {
// Create a condition that targets viewports at least 770px wide
window.onresize = function (event) {
console.log(event);
var mqMin = window.matchMedia('(min-width: 1400px)');
var mqMax = window.matchMedia('(max-width: 1800px)');
// check if media query matches#media (min-width: 30em) and (orientation: landscape)
if (mqMin.matches && mqMax.matches) {
console.log('Media Query Matched!')
// add css class for desktop
$('.rowComponent').addClass('jn-rowchange');
} else {
// remove css class if not desktop
$('.rowComponent').removeClass('jn-rowchange');
}
};
}
This is something that worked for me!
let mqMin = window.matchMedia("(min-width: 768px)");
let mqMax = window.matchMedia("(max-width: 960px)");
window.onresize = function () {
if (mqMin.matches && mqMax.matches) {
console.log("Inside Query parametara!");
} else {
console.log("Outside Query parametara!");
}
};

How to add css styles with JavaScript depending on the size of the browser

I am working with a Bootstrap 3 template and built a little JavaScript app. I am wanting to add a certain amount of margin to an element in one of the phases I created based on how big the viewport is. I have some code that I'm trying to work with but I keep getting the message Uncaught TypeError: Cannot read property 'matches' of undefined at MediaQueryList.myFunction. I cannot figure out why because all my variables that I am passing into the function as a parameter have values. I can see that the first value works because 17em is being applied but the value isn't changing when the size of the window changes. Disclaimer: I am fairly new to Javascript.
var x = window.matchMedia("screen and (min-width: 1200px)"),
y = window.matchMedia("screen and (min-width: 992px)"),
z = window.matchMedia("screen and (min-width: 768px)");
function myFunction(x, y, z) {
if (x.matches && phase === phases.crustType) {
doughSpan.style.marginLeft = "17em";
} else if (y.matches && phase === phases.crustType) {
doughSpan.style.marginLeft = "13em";
} else if (z.matches && phase === phases.crustType) {
doughSpan.style.marginLeft = "12em";
} else {
doughSpan.style.marginLeft = "0em";
}
}
myFunction(x, y, z);
x.addListener(myFunction);
y.addListener(myFunction);
z.addListener(myFunction);
I'd handle this via media queries. It's what they are designed for.
Set a class on doughSpan based on the phase. You'd do this where you're setting phase. Let javascript handle the manipulation of the DOM and leave the styling of it to CSS.
Something along the lines of the following
/*JS*/
function setPhase(phase) {
//Add the class "paseCrustType" to doughSpan if that is the active phase
doughSpan.classList.togggle("phaseCrustType", phase === phases.crustType);
}
/*CSS*/
.phaseCrustType {
margin-left: 0;
}
#media screen and (min-width: 1200px) {
.phaseCrustType {
margin-left: 17em;
}
}
#media screen and (min-width: 992px) {
.phaseCrustType {
margin-left: 13em;
}
}
#media screen and (min-width: 768px) {
.phaseCrustType {
margin-left: 17em;
}
}
When you call: x.addListener(myFunction), myFunction is only being passed the MediaQueryListEvent for x when it expects all three. You should generalize the function to accept a single MediaQueryListEvent and a margin to apply, and call addListener for each of your media queries.
Here's an example:
var x = window.matchMedia("screen and (min-width: 1200px)");
// declare y and z
var handleQuery = function(e, margin) {
if (e.matches && phase === phases.crustType) {
doughSpan.style.marginLeft = margin;
}
};
handleQuery(x, "17em");
// call handleQuery for y and z, passing along their margins
x.addListener(function(e) {
handleQuery(e, "17em");
});
// call addListener for y and z and handle them as you need
Check out the MediaQueryList.addListener docs for more details.

Is there a more efficient way of adding and removing these CSS classes with jQuery?

I have the below script that uses slidebars to show and hide a side menu.
I need to add and remove a CSS class to another div to tie things together. But looking at the way I am adding and removing classes I feel like there's a more efficient way?
function slidebarsStatus() {
var windowWidth = $(window).width();
breakpoint = 992;
if ( windowWidth > breakpoint ) {
controller.open( 'site-menu' );
$('.site-wrap').addClass('menu-active');
}
else {
controller.close( 'site-menu' );
$('.site-wrap').removeClass('menu-active');
$('.site-wrap').addClass('menu-inactive');
}
}
slidebarsStatus();
$(window).on( 'resize', slidebarsStatus );
Store the jQuery object as a variable:
var siteWrap = $('.site-wrap');
And chain your methods to the variable:
siteWrap.removeClass('menu-active').addClass('menu-inactive');
Or, if possible, media queries in your CSS:
#media screen and (max-width: 991px) {
.site-wrap {
/* active appearance */
}
}
#media screen and (min-width: 992px) {
.site-wrap {
/* inactive appearance */
}
}

detect browser size and apply css for every resolution

I have this function that I use to apply some css to a menu when browser is resized or when the menu is rendering on different resolutions.
My problem is this, why the browser is not interpreting correctly my function? because when I resize my browser in full mode from half mode the browser interprets only '800-1024' resolution but if I do ctrl+f5 in browser (clear all) interprets correctly my resolution so what is wrong in my function?
function renderMenuCorection(){
if ($('#containerHeader').exists()) {
var resizeObject = {
'0-640': '9px,2px,-3px,12px',
'640-800': '10px,2px,-5px,12px',
'800-1024': '10px,8px,-8px,15px',
'1024-1300': '12px,12px,-13px,11px',
'1300-2000': ',20px,-21px'
}
var win = $(window);
var win_width = win.width();
if (win_width > 0 && win_width <= 640) {
var value = getValueByKey(resizeObject, '0-640');
modifayMenu(value);
}
else
if (win_width > 640 && win_width <= 800) {
var value = getValueByKey(resizeObject, '640-800');
modifayMenu(value);
}
else
if (win_width > 800 && win_width <= 1024) {
var value = getValueByKey(resizeObject, '800-1024');
modifayMenu(value);
alert("I'm on: 800-1024 ," + win_width);
}
else
if (win_width > 1024 && win_width <= 1300) {
var value = getValueByKey(resizeObject, '1024-1300');
modifayMenu(value);
alert("I'm on: 1024-1300 ," + win_width);
}
else
if (win_width > 1300 ) {
var value = getValueByKey(resizeObject, '1300-2000');
modifayMenu(value);
}
}
}
function modifayMenu(value){
var vals = value.split(',')
$('#containerHeader').find('.roundMenuLi').each(function(index, item){
$(item).find('a').css('font-size', vals[0]);
$(item).css('padding-right', vals[1]);
$(item).css('padding-left', vals[1]);
$(item).find('#secondUl').css('margin-left', vals[2]);
$(item).css('padding-bottom', vals[3]);
});
}
function getValueByKey(obj, myKey){
$.each(obj, function(key, value){
if (key == myKey) {
returnValue = value;
}
});
return returnValue;
}
Thank you !
Use CSS3 and its media queries. Example:
#media (max-width: 500px) {
/* some CSS for small resolution */
}
#media (min-width: 1000px) {
/* some CSS for large resolution */
}
you main you want to create a responsive design this link can help you.
building responsive design you must consider
Flexible Grid
Flexible Images
Media Quires
/* below code play important part of your responsive design without that you cannot achieve what you want */
<meta name="viewport" content="width=device-width" /> /* put this before the end tag of head */
#media (max-width: 320px) {
}
#media (min-width: 720px) {
}
It's hard to tell from your code, but most likely you are only calling the function once on pageload. In order to make this do what you want, you will have to attach an event listener and call the code each time the window is resized.
As commented above, consider researching Responsive Web Design to utilize native browser functionality so you don't have to roll your own script to do this. A good place to start is an A List Apart article under the same name.
Media-queries are the best solution as Pavel remarks, besides they're much faster than all the access to the DOM you're making using your code.
The compatibility problem with IE8 can be solved using a JavaScript pluging called Respond.js. Haven't tried it but it seems a good solution to your problem.

Categories

Resources