There are many questions asking how to change the theme in Semantic-UI, but I have not been able to find even a question where it refers to changing the theme dynamically, i.e. after a webpack build.
I want to allow each user of a site to save their own preference for the theme. I have some users who prefer dark themes, and others who are color-blind, and others who have weak eyes and need larger fonts, or more contrast, etc.
I know it's possible to change the theme dynamically since the semantic-ui demos all do it. Unfortunately, the Theming page and all documentation I have seen describes how to change the site-wide theme, and apply that, in a new site-wide build. Or to customize that (still) site-wide build.
I think I'd be happy to just be able to add a class to the class list for an element (e.g. "github") and have it use that theme for that user (even if it was just for that element). But ideally, I'd like to have my page load an extra .less or .css file(s) with site-wide overrides for that user, for the user-selected theme.
I'm still pretty new semantic-ui and to applying dynamic changes to a webpack site. Any suggestions for how to apply additional less variable changes after build, or to reload entire Semantic-UI themes, like the demo does?
Note that demo site is not a link to GitHub; it's a look-alike with a paint can icon near the top-right which brings up a sidebar that allows you to change themes. Dynamically.
Update:
I need to test this now, but I may have an answer for my own question here.
It seems that the gulp build process typically compiles and combines all the less and other files into the dist folder as semantic.css, semantic.js, semantic.min.css and semantic.min.js. It also produces different individual component .css files in the dist/components subfolder, but (I think) if you're loading the full css file (e.g. semantic.min.css), that you don't really need the components subfolder. That this is present for those sites who want to optimize to the point of only including the .css files for the components they use?
So it's already processed and combined, and to swap themes, I think all that is necessary is to swap one semantic.min.css file with the output of the build for another theme. The .js files are the same, at least for default vs github themes.
If this is true, it's a matter of copying the semantic.min.css to an alternative file, for example, semantic.github.min.css and use that .css file instead. Or copy it to a theme subfolder like github/semantic.min.css. Then, in either case, update the DOM with a new href on the stylesheet originally referenced.
Summary: It looks like it's all in the semantic*.css file and swapping the output of different builds allows us to swap themes. I'll test this later tonight.
Update 2:
I updated the theme.config file with all github entries, then rebuilt the dist folder, copied the semantic.min.css as semantic-github.min.css to my static folder with the original, then just updated the href to select it:
// normally: <link rel="stylesheet" type="text/css" href="/static/semantic/semantic.min.css">
// non-default: <link rel="stylesheet" type="text/css" href="/static/semantic/semantic-theme.min.css">
function swapThemeCss (theme) {
console.log('Theme change to "' + theme + '".')
let sheet = document.querySelector('#theme')
if (!sheet) {
return
}
if (theme === 'default') {
sheet.setAttribute('href', '/static/semantic/semantic.min.css')
} else {
sheet.setAttribute('href', '/static/semantic/semantic-' + theme + '.min.css')
}
}
Oh also, in the example above, I gave the link an id of 'theme' to make it easier to find it and replace the href dynamically:
<link id="theme" rel="stylesheet" type="text/css" href="/static/semantic/semantic.min.css">
"So it's already processed and combined, and to swap themes, I think all that is necessary is to swap one semantic.min.css file with the output of the build for another theme."
Correct.
Depending on whether you're having per-user styles, or just multiple themes the user can pick from, you can simply have separate less files with per-theme overrides that can be compiled with webpack but perhaps not inserted into your index.html. Then you can dynamically add/remove the <link>s to depending on the user preference. The dynamic adding will cause a flicker from the default styles to the per-user theme styles if you're inserting the <link> tags via frontend javascript (because it must wait for the frontend JS to load, which will render the page/default styles in the meantime, then inject the new <link> and only show the new styles once those have been loaded). Add the per-user <link> tags serverside to make it seamless.
Related
This is my first post so I would like to say it's nice to join this community and I will do my best to help others but I'm the one that needs help right now.
--Problem
I've got problem with displaying proper styling of text retrieved from CKE with .getData(), saved into DB and displayed in article.
--When it works?
When I include this CSS:
<link rel="stylesheet" href="\js\ckeditor\contents.css">
in my base.html.twig <head> tag,this changes the css of the site.
--What do I need to do?
What I need to do to avoid conflict? or is there any method to render text without making it editable? Something like CKEDITOR.render(tagId)
--Some images:
With Regards
Wiktor
Please see:
https://docs.ckeditor.com/ckeditor4/latest/guide/dev_framed.html#content-styles-vs-page-styles
https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_config.html#cfg-contentsCss
If you are using classic CKEditor then its contents are held inside an iframe with a separate document. In order to style that internal document CKEditor attaches contents.css to it. Since internal styles in separate CSS files are not being saved together with HTML or merged into HTML it is important that you use same styles inside contents.css as you would like to see on your target page (where saved content will be used).
This is not CKEditor bug but simply a different approach you need to apply inside your application.
If you are creating content for different pages you can either create one large contents.css file or, in case of any styles conflicts multiple CSS files which you can load dynamically based on some logic (it will require writing some code to handle that) using contentsCss setting. Please note that in case of dynamic CSS switching you do not want to use contentsCss inside config.js file but directly in instance configuration on HTML page where you can use server-side tags to "spit out" correct configuration for CKEditor instance e.g.
var editor = CKEDITOR.replace( 'editor1',{
language : 'en',
// other configuration settings
// ...
contentsCss : [ '/css/mysitestyles.css', '/css/anotherfile.css' ]
}
You can use server-side tag which will return whole editor configuration or simply only this part contentsCss : [ '/css/mysitestyles.css', '/css/anotherfile.css' ] or even correct file paths when HTML is being rendered.
After asking on the Prestashop forum and receiving no reply I wanted to ask you guys and hope for an answer.
I am trying to add an animated snow plugin to my shop but after looking at the header.tpl file which instructs you to not edit - how do I add my own Javascript to the head of my template?
I duplicated the default-theme and I am working from that.
If the theme is default-bootstrap, then yes, you probably shouldn't modify it, if you intend to upgrade it (can be automatically upgraded using autoupgrade module).
Same can be true for 3rd party themes which are actively updated. But usually 3rd party themes don't get upgraded at all, which means you can modify theme templates. Because the templates are sort-of too complex to be extended by a child theme, it is ok to edit them directly. PretaShop doesn't have child-parent theme system. Just edit the templates directly.
If you would like your changes to be portable accross themes, then you should probably make a module. Inside the module use special functions to add .js and .css files to header:
mymodule.php
...
public function install()
{
...
$this->registerHook('displayHeader');
...
}
public function hookDispayHeader()
{
$this->context->controller->addJS($this->_path.'js/script.js');
$this->context->controller->addCSS($this->_path.'css/style.css');
}
If you need a quick way to add, just edit theme's global.css and global.js
You may also add the stysheet and script to autload folder:
themes/theme1/css/autoload/ and
themes/theme1/js/autoload/. Files inside these folder will be loaded for all pages.
Add custom JS or CSS in theme, using this :
<link rel="stylesheet" href="{$css_dir}bootstrap/bootstrap.css" type="text/css" media="all" />
<script type="text/javascript" src="{$js_dir}bootstrap.js"></script>
$css_dir links to your theme css directory.
$js_dir links to your theme js directory.
Assuming you're working on your own theme (or duplicated the default-theme for custom use)
Refresh css without reloading page, css defined in App_themes folder and theme referred through webconfig.
I do not have any reference of CSS file on the page, it is done through referring theme name in webconfig.
Tried many ways but failed to get any output:
not able to use versioning like this:
<link ... href="http://sstatic.net/stackoverflow/all.css?v=c298c7f8233d">
Tried CSSrefresh.js to automate the process but failed to get the actual result.
So is there anything which refresh my page with the latest css without reloading the page?
EDIT: When you refresh a page, some of the elements in that page (like CSS and JavaScript files, images, etc.) may not be updated from server, because they are cached by the browser, so you may be unable to see your latest updates. What you need to do is to somehow prevent the browser from using the cached version of the files and request these content again.
One way to do it is to disable caching for your CSS or any frequently updated files. To do it in ASP.NET, you change Web.config file in the directory you want the cache to be disabled (in your example App_themes). If that directory does not contain a Web.config file, you can create one. To disable caching completely, you can add the following lines to Web.config (if some XML elements are already present, append new children to them):
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
</system.webServer>
</configuration>
Instead of disabling cache completely, you can set it to a short time, like 5 minutes. To do this, change the clientCache element in the above example to this:
<clientCache cacheControlMaxAge="00.00:05:00" cacheControlMode="UseMaxAge"/>
Bear in mind that disabling caching is a very bad idea and impacts performance very badly and you shall not do it unless absolutely necessary and if all other solutions fail.
A (better) solution to the problem is using versioning (as you mentioned), and it should work. What you do is change the way you link to your CSS file from <link rel="stylesheet" href="style.css"> to <link rel="stylesheet" href="style.css?v=1"> (a version is appended as a parameter). You do not need to change the name of the actual CSS file on disk. Now, the browser will cache style.css?v=1. If your CSS changes and you want this change to be applied immediately, you manually change all links to your CSS and increment the version (<link rel="stylesheet" href="style.css?v=2">). No browser has style.css?v=2 in its cache, so all browsers send a new request to get the file.
Manually changing all CSS references each time they change is very cumbersome. To automate this process, you can use the bundling and minification plug-in in ASP.NET (it is only available in later versions of ASP.NET). Bundling and minification is a very useful optimization technique that you should be using anyway to improve the performance of your site, so enabling it is a good idea. The bundling plug-in, among other things, automatically changes the version parameter once a file changes.
Enabling bundling is a little different depending on your project type (ASP.NET MVC, Web Forms, etc.). Please see documentation on how to use it for MVC here and for Web Forms here.
If you want the style of page to dynamically change, include all theme CSS files in your initial page load, but each theme CSS rule must be edited so its selector only works if there is a specific class name defined in parent. You can then use JavaScript to add/change the class name in the parent node to use different themes.
For example, your CSS would be
.theme1 body { background: red; font: 'sans-serif'; }
.theme2 body { background: blue; font: 'serif'; }
And your HTML would be:
<html class="theme1">
<body>
</body>
</html>
Then if you want to change theme, change class name on HTML element to 'theme2'.
I downloaded and customised a website template to fit my needs. The template came with a number of folders and files including js and bootstrap files.
Everything seems to work fine until I tried to integrate a php script which also happens to be designed and includes a number of js and bootstrap files.
I used firebug to debug the conflicts.
When I include the header and footer files together with the associated js and bootstrap files, the script loses most of the design (ie; the navigation panel).
I noticed that the classes defined in the template bootstrap css files are the same as the ones in the scripts own bootstrap css file.
How can i fix this?
Is there a way to exclude the main sites bootstrap files from affecting the installed script or vise-versa?
I haven't used bootstrap and don't know much about it, but basically if you want to save the bootstrap styles just load them after your script.
Something like this:
<link rel="stylesheet" href="css/YOURCSS.css" />
<script src="js/YOURJS.js"></script>
<link rel="stylesheet" href="css/bootstrap.css" />
<script src="js/bootstrapJS.js"></script>
These are the files you told you are including...
public_html/bootstrap/css/bootstrap.min.css
public_html/folder/subfolder/script/theme/css/bootstrap.css
<link type="text/css" rel="stylesheet" href="/bootstrap/css/bootstrap.min.css"/>
<link href="/folder/subfolder/script/theme/css/bootstrap.css" rel="stylesheet"/>
Two assumptions :
Both the sets of files are the same in code.
Then, no problem, but it is not, from what you said.
Both the sets are equal by name but different by content. Then, if those files contain classes (or #id rules) of similar names, all the rules will be ordered in First come first read basis, and if there are multiple rules for a single property, the last rule for that property will be applied.
Example:
h1,h2, .heading, #heading{
font-family:georgia; /* from first file in the include order they are specified in html */
font-family:verdana; /* from second file */
font-family:arial; /* from third file */
},
then,
the last rule : font-family:georgia; /* from the third file */ will be applied.
Debugging such things would be harder if you like to do. Because you can not guarantee the way how they get merged up. If all the code is written by yourself, you could have used a minifier like this which removes all duplicates. But that is not the case.
Finally, you said Everything seems to work fine until I tried to integrate a php script which also happens to be designed and includes a number of js and bootstrap files.
Here, it is better to remove CSS classes that are similar in names from the ones that came along with your php script folder.
Is there a browser add-on (for firefox or chrome) that would easily let me open a non minified version of a script file?
eg, a production website would load script.min.js, but usually the script.js would also be available in the same directory.
same goes for some css files (style.min.css or style.css)
the .min. notation seems to be used quite a bit
I'm not looking for a pretty-printer, like in this question:
Is there a plugin that allows me to automatically unminify the Javascript included on a site?
but for something that would automatically discover the correct unminified file (which would include comments etc)
Couldnt find any through google, but perhaps I missed one?
Here is a bookmarklet
<a href="javascript:(function() {
var scr=document.getElementsByTagName('script');
var pop = [],html='';
for (var i=0;i<scr.length;i++) {
if (scr[i].src.indexOf('.min.js')!=-1) pop[pop.length] = scr[i].src.replace(/\.min/,'');
}
if (pop.length==0) html += 'No .min.js found';
for (var i=0;i<pop.length;i++) {
html+='<br/><a href='+pop[i]+' target=_blank>'+pop[i]+'</a>';
}
var div = document.createElement('div'), dst=div.style;
dst.position='absolute';dst.top=0;dst.zIndex=9999;dst.backgroundColor='white';
div.innerHTML=html;
document.body.appendChild(div);
})();">unMin</a>
To activate, save the above in a file with html extension, load the page into the browser and drag the link to the link bar
Alternatively copy the href into an existing bookmark and rename it.
Sometimes recovering an "unminified" file is not straightfoward, as can happen if you concatenate Javascript and CSS files for production.
Something you can do is have a folder containing the original files and another production folder that is build via a script. This way switching modes is just a matter of changing from /dev/ to /dist/ in the URL
YAML Debug is a bookmarklet that will display all the stylesheets of a page and allow you to activate/deactivate each one (in the Stylesheets tab).
You can combine it with alternate stylesheets, the one used as styleswitchers (as in (1))
<link rel="stylesheet" href="screen.min.css" type="text/css">
<link rel="alternate stylesheet" href="screen.css" type="text/css" title="Not minified">
(1) http://tantek.com/CSS/Examples/codeisfreespeech.html
Go to the page and then in Fx/IE/Opera maybe Safari and Chrome, press Alt key to open the old plain menu, choose Display menu / Page style and finally no style option or current style or any alternate style you added.
Quite old school but still useful :)