How to prevent dark mode flickering on a website? - onclick

I have implemented a dark mode to a WordPress site using a simple technique like this one found in https://github.com/avecNava/dark-mode.
<script>
//runs on every page load, checks local storage for last mode and applies dark mode if found
document.body.classList.toggle('dark-mode', localStorage.getItem('darkmode') === 'true');
//the function must be called when dark mode is clicked by the user
function switch_mode(){
const dark = localStorage.getItem('darkmode') === 'true';
localStorage.setItem('darkmode', !dark);
const element = document.body;
element.classList.toggle('dark-mode', !dark);
}
To prevent flickering I've tried to place the first row inside the head tags (via header and footer scripts plugin) but it doesn't seem to work. I've seen solutions to this problem but they all seem to be built different from the start so it's hard to apply those solutions to the code I'm using.
To trigger the switch, I'm using a clickable icon that has an onClick() property that calls the function. Is there any solution to my problem or should I just start the whole thing from scratch using a different technique for example a checkbox trigger?

Related

next.js styles doesn't update on first render

Using next.js with SSR I'm having a strange problem.
My website renders as expected server-side and is served to the client with styles. There are no surprises here when I'm visiting the website on a laptop everything looks as expected.
However, when I visit the website on a mobile device (or simulated smaller window), the first render is rendered with the same styles as my desktop styles, even though my mobile media query returns true
I'm using https://github.com/wintercounter/use-breakpoint for most of my media queries.
Which looks like this:
const { 'isMobile-': isMobileMinus } = useBreakpoint()
and my layouts etc. should change based on whether isMobileMinus is true or false.
For example, this antD component is supposed to switch from horizontal to vertical if it's a mobile device.
<Space size="middle" direction={isMobileMinus ? 'vertical' : 'horizontal'}>
What is really interesting is that when I render the webpage in a small window the size of a mobile device I can console log isMobileMinus to be true, but my components do not update until I either resize the window (and it's true again) or I navigate to another page and back.
It acts as if isMobileMinus was false, but only for that specific component.
I can even render the value of isMobileMinus in the component and it will render true on first render, but the components I have acts as if it was false until I make another update.
I find this very strange as the component is clearly re-rendering with the correct value, but it does not update the styles of the components that were styled via SSR?
This problem is not just limited to the above hook based media queries but also other things.
For example I have 2 buttons that are rendered on SSR called "login" and "Signup" which are supposed to be white and green respectively.
However when the webpage renders if the user is already logged in. It should render 2 new buttons called "Log out" and "Dashboard" which are red and blue respectively.
But somehow on first render. The text of these buttons will update to logout and dashboard, but the styles of the buttons will be white and green (incorrect).
These are completely different components, but next.js still keeps the old styles?
if (loggedIn) {
return (
<Space>
<LogoutButton onClick={handleLogout} />
<DashboardButton onClick={handleDashboardClick} />
</Space>
)
}
return (
<Space>
<LoginButton />
<SignupButton onClick={showSignup} />
</Space>
)
There seems to be some really strange thing with next.js where it will update the content of the HTML, but refuses to update the CSS when a component is re-rendered on the client-side.
Anyone knows how to fix this?
I tried making a copy like suggested here: How to immediately re-render client-side using React + NextJS after initial server-side render? which seems to be a similar issue.
const breakpoints = useBreakpoint()
const copy = lodash.cloneDeep(breakpoints)
const { 'isMobile-': isMobileMinus } = copy
console.log('🔈 ~ isMobileMinus', isMobileMinus)
But that did not work for me either.
I'm on "next": "11.0.1",
I found 1 solution but it feels more like a hack than a solution.
If I wrap my components in process.browser && (<Component />) then the component will not render during SSR, and only render client-side.
This causes the component to render correctly when the webpage is loaded.
But of course I would ideally like to take advantage of SSR, and just update the styles client side :(
Note that this hack also causes console errors, so it is definitely not recommended. It seems like the use-breakpoint library is incompatible with SSR frameworks.

Handle window.scrollTo on svelte on a single page application

How can i go to a window position after an update on my Repl example? When i scroll down and click on a card and go back to the main window it allways jumps to the top. I have tried to insert window.scrollTo on afterupdate and also beforeupdate, inside the OpenCard.svelte also inside the App.svelte but i cant figure it out. What would be the best solution for this?
Repl
There is more than one solution for this, because this is quite a lot of code for such a question.
one solution would be to add this line to your showHome function
function showHome() {
visible = true;
requestAnimationFrame(() => window.scrollTo(0,100)); // That's the line
}
HOW IT WORKS:
The reason this solution works is because you condition the entire app on the visible variable, so after setting visible = true; the app hasn't updated yet, and therefore calling window.scrollTo immediately will just scroll before the refresh.
thus putting it inside a requestAnimationFrame will wait for the next redraw of the DOM, making the scroll only after the DOM's update.
Another solution would still require requestAnimationFrame,
There's no avoiding it using.
It will require to create a reactive statement like this:
$: if (visible) requestAnimationFrame(() => window.scrollTo(0,100));
That way your app will always know when to change the scroll based on your visible variable's value.
I think you should go with the second solution, it's more stable on future changes.
To learn more about requestAnimationFrame and how to use it: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame

visibility behaviour disable callbacks seems not working

In trying so recreate the right following menu in semantic ui site,
I put visibility on the different sections of the page
that set to active the corresponding menu entry. It works ok.
But when I simply click on the menu entries, that also triggers visibility callbacks, because the page is moving
With this set up
.on('click', function(event) {
event.preventDefault();
var el = $($(this).attr('href'));
$(this)
.addClass('active')
.siblings()
.removeClass('active')
;
$('.card-item').visibility('disableCallbacks');
$('html,body').animate({scrollTop: el.offset().top});
$('.card-item').visibility('enableCallbacks');
});
I intended to go to the desired place el without triggering the visibility callbacks of all sections with visibility set, that need to be crossed to get to el, but that is a no op.
I tried also 'disable callbacks' instead of 'disableCallbacks'
I tried it manually in the console , same thing.
Thanks
The behavior is 'disable callbacks' as two words.
So:
$(selector).visibility('disable callbacks')

Unable to trigger modal-dialog show in Meteor template

I have a modal dialog in my template. This dialog needs to be triggered from the code programatically. So I need to show the modal through javascript, as I cannot have a data-toggle button to launch the modal-dialog.
The modal was working with bootstrap but with bootstrap-3 its not showing up, even though I can show it from the console directly. the problem here is how can I execute javascript post the template render, to launch the modal-dialog.
There is a Template.rendered/created function which is called, and inside this this.autorun(runFunc) is supposed to run the code to update the DOM element. This is called correctly, but I still cannot trigger the modal to show-up.
Template.createDialog.created = function() {
console.log("teamplate created");
this.autorun(function(){
$('#myModal').modal('show');
});
};
Update:
This works:
Template.createDialog.rendered = function() {
console.log("teamplate created");
this.autorun(function(){
$('#myModal').modal('show');
});
};
Using the rendered function, I am able to trigger the modal to show up. But the problem is that rendered and created both are only called once. And I need a way to trigger the modal dialog consistently if a condition is reached.
This bootstrap modal dialog with meteor is turning out to be painful and hacky. Is it not possible to show/hide modal using some class parameters?
Modals can be tricky to get right in Meteor for exactly the reasons you've discovered. I don't use Bootstrap, but the basic principle is that you need to trigger the modal programatically so that you can run the relevant framework code once you know the html has been rendered but still retain reactivity (this is certainly the case with Foundation and Semantic-UI modals) .
In your use case (which appears to be a single modal), this shouldn't be too much of a problem. Set a reactive variable modalVisible (a Session variable or similar), and use that to show or hide the modal as required.
this.autorun(function(c) {
if (Session.get('modalVisible')) {
$('#myModal').modal('show');
} else {
$('#myModal').modal('hide');
}
});
If you put all of that in the rendered callback then it will only try to show the modal once it's been added to the DOM (without which you'll get an error and the computation will stop running, breaking reactivity). Note that you shouldn't make rendering of the template dependent on a reactive variable - it should always be rendered but only visible based on the value of the modalVisible Session variable.
Apologies if this is too simple for your use case - if so I would recommend investigating the several packages on Atmosphere for Bootstrap modals as others will almost certainly have faced the same problem.

How to change css style locally and save this changes

i have an webapp and i need to onclick change css style, but i need to save this change in the webapp instaled into the phone of my user, and only in his phone. The javascript for onclick change css style it's working but i don't have no idea to how to save this css changes.
Can somebody help me with this?
Since now thanks
In general CSS styles can't be directly saved on an HTML client.
What you can do is make an Ajax call back to your server and save the information there. The next time the user asks for the page send HTML with the appropriate style class already on the element you wish to style based on the saved information.
There are several hackish client side possibilities involving JavaScript & cookies or local storage but I would avoid that sort of solution if at all possible since it's very likely to lead to an annoying flicker as the page loads and renders styled one way and then the JavaScript finally runs and corrects the style.
To elaborate on my comment:
el1.addEventListener('click', function() {
el2.style.color = 'red';
localStorage['color'] = el2.style.color;
})
And then on startup:
window.addEventListener('load', function() {
if (localStorage['color']) {
el2.style.color = localStorage['color'];
}
}
Of course, you may want to add error checking and fallbacks as appropriate.

Resources