Toggle Display State with Button and Media Query - javascript

I'm looking for the best way to have display state that can be toggled via a button on the page, but that can also be overridden based on a media query. On large screens I want to default to a horiz layout, and provide the choice to toggle a vert layout instead. On smaller screens, I want to default to the vert layout and not allow the toggle.
My current solution relies on cascading to override styles in the stylesheet which I would like to avoid since it requires my styles to be in a specific order.
HTML:
Apply a default layout of layout--horiz. layout is also applied in order to override the specific layouts with #media queries.
<div id='layout' class='layout layout--horiz'>
<a href="#" id='btn'>Toggle</a>
<p>This</p>
<p>is</p>
<p>a</p>
<p>test</p>
</div>
CSS:
In the #media query for small screens: hide the toggle, and hardcode the vert styles to the layout style to override the layout--horiz if applied.
#btn {
display: block;
}
.layout--horiz p {
display: inline;
}
.layout--vert p {
display: block;
}
#media screen and (max-width: 600px) {
#btn {
display: none;
}
.layout p {
display: block;
}
}
JS:
Toggle the specific --horiz and --vert classes on button click.
$('#btn').click(function() {
$('#layout').toggleClass('layout--vert layout--horiz');
});
This solution works decently, but I'm wondering if there is a better way to accomplish this.
Note: Here is a codepen to play with.

Your solution isn't far from optimal barring inclusion of your JS into a frontend framework. This is probably why you're receiving comments directing you to code review. To improve your solution use only one selector for state change. This will invoke two states to your layout layout--horiz and a default state. It's easy to make this change once you switch your media query to select for large displays instead of small ones.
HTML:
<div id='layout' class='layout layout--horiz'>
<a href="#" id='btn'>Toggle</a>
<p>This</p>
<p>is</p>
<p>a</p>
<p>test</p>
</div>
CSS:
#btn {
display: none;
}
.layout p {
display: block;
}
#media screen and (min-width: 601px) {
#btn {
display: block;
}
.layout.layout--horiz p {
display: inline;
}
}
JS:
$('#btn').click(function() {
$('#layout').toggleClass('layout--horiz');
});

I think a better way of doing this could possibly be to have two separate style sheets one with horizontal layout and the other with vertical layout and then you can switch the style sheets on click function to get the preferred layout. Here is a link to something I found really quick.
https://www.developphp.com/video/JavaScript/Change-Style-Sheet-Using-Tutorial-CSS-Swap-Stylesheet

Related

Media Queries or JavaScript to hide an element on certain screens

We have a section on the page that needs to be hidden on small phone screens, and appear on larger screens.
The easiest way to do it would be to use CSS media queries.
.section {
display: none;
}
#media (min-width: 900px) {
.section {
display: block;
}
}
However, this would keep the section in the DOM, thus potentially making it less efficient.
Alternatively, we could toggle the existence of the section using a state in our JavaScript framework (React in our case, but not important for the question).
My Question is: When is it better to use one, and when is it fine to use the other?

Mobile navbar shows options next to each other instead of underneath each other

The website URL is https://www.mh-rp.com/
I have this mobile navbar but the options should be underneath each other and not next to each other.
the problem
In this case display : grid can solve your issue. But as It will work in all sizes so limiting it to mobile screen only, you can wrap your CSS inside media-query block #media (max-width:1000px) {}
Try it:
#media (max-width: 1000px) {
.navigation {
display: grid;
}
Try this one <ul class="navigation" style="display: grid;">

ParticlesJS component in React is hidden with media queries but not coming back to display

I am using the ParticlesJS package for my ReactJS application. It displays at the beginning. I want to hide it when the screen size is under 600px. It sets the display to none, however when the screen is resized back above 600px, the particles element doesn't set display back to block, so it's not displayed again.
html/jsx:
<div className="particles-container">
<Particles params={particleParams} className="particles" />
<div className="home-banner-content">
<img src="./src/style/img/logo_banner.png" />
</div>
</div>
css:
#media only screen and (max-width: 600px) {
.particles-container .particles {
display: none;
}
}
#media only screen and (min-width: 600px) {
.particles-container .particles {
display: block;
}
}
After digging in a bit I saw that the Canvas's height is set to 0 when display: none; is set via the media query.
I'll have to dig in more to get the correct answer to as to why that might be happening. Will return with an update to this answer with a proper explanation regarding this.
Continuing, when your media query sets display: block; the height of the canvas still remains 0 and thus you are unable to see it.
To fix this you can either listen to window resize events inside the javascript code (in case you're resizing).
But in case you're going to fix this for mobile then you can check for window width inside the javascript itself and conditionally render the Particles component.
Also, if you provide a "fixed" height to the Particles component as a prop, your media query will work.
Here, you can see a demo: https://codesandbox.io/s/rw8666x11o

Adding CSS media queries with javascript or jQuery

I'm having some issues trying to add media queries with jQuery/javascript. I have a <div class="container"> hidden on small screens with display: none. I want to use the code below to make it show up, although I don't get any errors nothing changes.
$('.container').append('<style type="text/css">#media screen and (min-width: 1012px){ .container { "display": "block"}}</style>');
Any suggestions? Thank you.
It's will work fine if you only delete double quotes form "display": "block"
$('.container').append('<style type="text/css">#media screen and (max-width: 1012px){ .container { display: block}}</style>');
but I think better if you change your selector
$('head').append('<style type="text/css">#media screen and (max-width: 1012px){ .container { display: block}}</style>');
You can use
document.querySelector('style').textContent +=
"#media screen and (min-width: 1012px){ .container { display: 'block'}}"
Get style element and add your new rules, and your html add if no exists
<style>......</style>
The answer of CMedina is quite good, but it appends to the first style element in the document. This could be problematic in two ways:
a) There might not be style element (because <link rel="stylesheet">);
b) There might be more than one style element. Appending style rules to the first one might be overwritten by later ones.
So here's my tactic:
create a new <style> element; fill with desired content; append to the body so it comes last
const styleSheet = document.createElement('style');
styleSheet.textContent = '#media print { /* ... */ }';
document.body.appendChild(styleSheet, 'beforeend');

Replace carousel with single div in CSS using media queries

I'm working in a website for mobiles, tablets and desktops. This website in its desktop layout has a carousel that it is defined in the html like this:
<div id="carousel">
<div class="carousel-slide carousel-slide-active">
</div>
<div class="carousel-slide">
</div>
</div>
Class carousel-slide define an slide of the carousel, and carousel-slide-active, the slide being showed at the moment (controled by Javascript).
For the mobile layout, I don't want to show this carousel. My idea is to show just the first slide (each slide is basically a background color and an image). The question is, how can I do this? Actually I'm using CSS media queries to rearrange all the elements in each device but I don't know how to hide all unused slides and disable the Javascript (this javascript controls the background code (random) and the positioning). Which is the cleanest way to replace the carousel with a simple div with the image and a random color?
You can't disable the JavaScript unless your carousel plugin has a built-in method for it. If it doesn't have that, there is just no way.
Assuming all of the carousel slides actually appear inside of the carousel-slide-active div, you can do something like this:
#media screen and (max-width: 700px) {
.carousel-slide {
display: block;
}
.carousel-slide.carousel-slide-active: {
display: none;
}
}
This will make sure your "active" div is hidden and the other one is displayed. All html elements inside of the active div will also be hidden because their parent is hidden.
You can potentially add the !important flag to those css properties if you need to override some styles being created by the JavaScript. In that case it would look like this:
#media screen and (max-width: 700px) {
.carousel-slide {
display: block !important;
}
.carousel-slide.carousel-slide-active: {
display: none !important;
}
}

Categories