How to change less parameters and compile css dynamically in the browser? - less

I am trying to implement a basic theme roller functionality using LESS CSS.
Suppose I have the following Less Code, which compiles to a .css file included in the page:
#main-background-color: #809BB8;
body
{
background-color: #main-background-color;
}
I would like to change the #main-background-color dynamically with javascript based on an user action (Color Picker) and compile the LESS code dynamically and refresh the styles of the page so that the user changes are reflected immediately in the browser.
Is this possible at all?
Please advise!
Thanks

you could try using less.js functions like:
less.refreshStyles()
or
less.modifyVars()
you can maybe read some more on this here: Dynamically changing less variables
Something along this lines with JavaScript and modifyVars might work:
var $picked-color = "#809BB8";
less.modifyVars({
'#main-background-color': $picked-color
});

Related

Server Side Rendering Vue with ASP.NET Core 2

I'm trying to understand the usage and limitations of server side rendering with vuejs when using aspnet core.
I used this starter kit for aspnet core and vuejs to setup a simple vue site, which is running based on the code here: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/master
I then modified the project to update the aspnet-prerendering and added vue-server-renderer, compiling a hodgepodge of sources to cobble together this update: https://github.com/selaromdotnet/aspnet-vue-ssr-test/tree/ssr
If I run this project, the site appears to load fine, and if I turn off the javascript in the browser, I can see that it does appear that the server-side rendering executed and populated the html result:
however, because JavaScript is disabled, the content isn't moved into the dom as it looks like it is trying to...
My understanding of server-side rendering is that it would populate the html entirely and serve a completed page to the user, so that even if JS was disabled, they'd at least be able to see the page (specifically for SEO purposes). Am I incorrect?
Now I believe modern search engines will execute simple scripts like this to get the content, but I still don't want a blank page rendered if js is disabled...
Is this a limitation of server-side rendering, or perhaps specifically ssr with vue and/or aspnet core?
or am I just missing a step somewhere?
Edit: more information
I looked at the source code for what I believe is the method that prerenders the section here: https://github.com/aspnet/JavaScriptServices/blob/dev/src/Microsoft.AspNetCore.SpaServices/Prerendering/PrerenderTagHelper.cs
The line
output.Content.SetHtmlContent(result.Html);
has a null value for result.Html. However, when I manually edit this value to put a test value, it also doesn't render to the output html, and the app div tag is still empty...
If I'm doing something wrong to populate the result.Html value with the expected output, that's one thing, and I would appreciate some help in doing that, especially since the output html appears to be found, since it's in the script that immediately follows...
However, even if I were to populate it, it appears it's being skipped, as evidenced by me manually changing the value. is this a bug in the code or am I doing somethigng wrong, or perhaps both?
As you correctly noticed, for your project, result.Html inside the tag helper is null. So that line cannot be the location where the output is being generated. Since the HTML output from your prerendering script also does not include a script tag, it is clear that something has to generate that. The only other line that could possible do this is the following from the PrerenderTagHelper:
output.PostElement.SetHtmlContent($"<script>{globalsScript}</script>");
That would fit the observed output, so we should figure out where the globalsScript comes from.
If you look at the PrerenderTagHelper implementation, you can see that it will call Prerenderer.RenderToString which returns a RenderToStringResult. This result object is deserialized from JSON after calling your Node script.
So there are two properties of interest here: Html, and Globals. The former is responsible for containing the HTML output that finally gets rendered inside the tag helper. The latter is a JSON object containing additional global variables that should be set for the client side. These are what will be rendered inside that script tag.
If you look at the rendered HTML from your project, you can see that there are two globals: window.html and window.__INITIAL_STATE__. So these two are set somewhere in your code, although html shouldn’t be a global.
The culprit is the renderOnServer.js file:
vue_renderer.renderToString(context, (err, _html) => {
if (err) { reject(err.message) }
resolve({
globals: {
html: _html,
__INITIAL_STATE__: context.state
}
})
})
As you can see, this will resolve the result containing just a globals object with both html and __INITIAL_STATE__ properties. That’s what gets rendered inside of the script tag.
But what you want to do instead is have html not as part of globals but on the layer above, so that it gets deserialized into the RenderToStringResult.Html property:
resolve({
html: _html,
globals: {
__INITIAL_STATE__: context.state
}
})
If you do it like that, your project will properly perform server-side rendering, without requiring JavaScript for the initial view.

less / css selector values based on selectors from import file outside my control

#seven-phases-max I have refactored my code a few times based mostly on your answers to my stackoverflow.com posts but would like to get your feedback to my latest and hopefully final variation:
Ultimately I ended up using :extend to get copies of css properties of styles not under my control:
Below is example of approach I've used in several places create css from base css/less selectors defined in less files outside of my control and optionally over-ridden in another less file outside my control:
.CODE-COLORING-ICON {opacity: 0.0};
Below code works works with and w/o above css / mixin line
.CodeMirror-gutters:before,
.CodeMirror-gutters:hover:after {
&:extend(.CODE-COLORING-ICON);
}
In other places, I created created empty selectors fearing less would not like an extend like above with ".CODE-COLORING-ICON" not defined. I was surprised the above code worked.
The end game is to merge css from theme with override values from another file.

LESS: How to change variables on the fly directly from website

I would like that a visitor on my site could change values of some LESS variables that I defined in my LESS stylesheets.
For example if I declared the following rule:
#color-of-text: blue;
body
{
color:#color-of-text;
}
Obviously, website has blue text. But I would like that a user could select (is not important in which way... a dropdown, or checkbox or whatever) a different value, changing for example #color-of-text from 'blue' to 'red', like I wrote "#color-of-text: red;" directly in my less file.
Obviously this change should happens on the fly, withour reloading the page.
How to obtain this?
You can't edit the LESS. LESS gets compiled down to CSS eventually and that's what's sent to your browser.
To answer your question though, you would use javascript and have it change the style property of the element on the page you wanted to change color based on user input.
If you want that color choice to persist over multiple pages loads / visits, that's another story.
This has nothing to do with less.
You could generate different css file changing color variables of same less and then ask to client which css it would see.
You can store the choice in a cookie and then print the desiderd file in PHP every request page of the visitor
$skin = isset($_COOKIE['skin'])? $_COOKIE['skin'] : 'default';
echo '<link rel="stylesheet" type="text/css" href="path/to/'.$skin.'.css" />';
During the select you can refresh the page or change the css via javascript.

TwitterBootstrap + mvc, how to pass dynamic width to boostrap .less class

i am using TwitterBootstrap and i want to pass button width dynamic..like below code
I want to pass "#wth" value Dynamically from client side(from view(MVC)).
Right now it's comingStatically on varibles.less file....But i want to pass directly from view(MVC).
so, what is the Best Solution ?
Although it gives the impression of being able to do dynamic things if you use less.js in the browser, those styles are all compiled into CSS files, and have fixed values by the time they are applied to your html. So you can't change values of Less variables after the page loads.
If you need to change the width of a button dynamically based on a few pre-set sizes, I'd say you should add classes to your css (small, medium, large, etc.), and then dynamically add that class to your CSS via Jquery's addClass method.
If you need to set the width directly, I'd use Jquery's css method.
If you're going to be doing a lot of this sort of thing, you may want to look into using a data-binding library that can bind a Javascript object to your html styles, such as Knockout.

remove redundant css rules from dynamic website

I'm trying to reduce the size of my CSS file. It is from a template which is very CSS & JS heavy. Even with CSSMin the CSS file size is 250kb.
Whilst I use alot of the CSS - I know I dont use it all. So I'm trying to work out which styles can be removed. I'm aware of Dust-Me selector - but that only takes a static look at the website. With HTML5 and CSS3 - websites are now very dynamic, and most of my CSS occurs from dynamic events, or 'responsive' events i.e. Bootstrap.
Question: Is there a tool which 'records' all my CSS use on a website for a perioid of time, so I can go and click/hover/move over each element and interact with my site. Then at the end let me know which styles were & were not used?
CSS Usage is a great extension for firefox. It tells which css are currently used in a page.
Link: https://addons.mozilla.org/en-us/firefox/addon/css-usage/
There are two tools that I think might help you out.
helium is a javascript tool that will discover any unused css rules.
csscss is a source code analyzer that will report any duplication. I'm biased because I wrote csscss precisely because I couldn't find anything that did this. But many people seem to find it useful.
250kb is really such a big figure for just CSS files.
The templates generally have all the CSS required for all the pages in a single file.
I would suggest:
Do not cut your CSS code, they might be needed some point of time.
Instead i would suggest, break your CSS file into number of small files for different page stylings,
such as a different CSS for login page, different CSS file for home page, etc.
Read your own CSS and HTML code vigorously to find out which significant part of CSS code is used in which HTML section.
Update:
You may try Removed Unused CSS - CSS optimizer.
I personally did not use it just hope it works for you.