I have some pixel differences between Chrome and Safari, I haven't been able to find a suitable way to deliver different styles to each of them using a css hack.
I have been able to fix it with javascript but there is a delay as the page loads and before it is applied, so the user sees movement.
function chromeStyle() {
if (window.chrome) {
var a = document.getElementById("id");
if (a) {
a.style.marginLeft = 5px;
}
}
}
I know that it is possible to place the following code into the head of an html document and then use ".JS .mystyle{}" in a stylesheet to apply styles where javascript is enabled.
<script type="text/javascript">
document.documentElement.className = 'JS';
</script>
I wondered if in a similar manner it would be possible to create a selector for Chrome that could be applied in a stylesheet?
if (window.chrome) {
create a selector for chrome here
}
and in the stylesheet apply it as ".chrome .mystyle{}".
Thanks.
I dont know if this is easier then what you're trying to do with JS.
But when i need to override certain styles for a specific browser I just create a check for the browser serverside, and then include an extra stylesheet that overrides the base styles.
Related
How can I do this(or something alike this) tooltip in only javascript without linking any template styles (I don't want to implement It to all the tooltips on the whole page). I'm designing the webpage on SharePoint which deletes all the ...
https://www.w3schools.com/css/tryit.asp?filename=trycss_tooltip_top
You can always add inline styles via JS.
var a = document.getElementsByClassName("class-name");
a.forEach(function(e) {
e.style.property = "value";
});
For adding :hover effects however, I think you need to append a stylesheet. Example.
Your other option is to use mouseover effects, but that is ridiculous when :hover exists.
Is there any easy way to take in a block of CSS from the user from an textarea and add this styling to the styling for a specific div?
See I'm creating a simple code preview tool like codePen, so far I have two textarea inputs, one for Html and one for CSS, as the user types in the Html input this updates the preview pane, this works, now I want to do it for CSS.
CSS textarea could contain a few blocks like:
h1 {
font-size:23px;
}
.myClass {
//Somestyle
}
Now I want this CSS to be contained in the
<div id="preview"></div>
So it doesnt effect the rest of the page, so a manual example would be
$('preview h1').css('font-size','23px');
Anyway to automate this?
Do it like this. Hope it works.
Add a style block for dynamic styling.
<style id="dynamicCss">
</style>
on the apply button click handler, set the style
$('#btnApplyStyle').click(function(){
$('#dynamicCss').html('').html($('#txtaCustomCss').val());
});
See the Fiddle here.
Please use developer tools to see the new style tag added to head section.
This script simply adds rule to the document. If you don't want that behavior, you can use this plugin in combination with my logic to set scope for rule. You will need to place the style tag inside of the container and add a scoped attribute to style for it to work. Please see the documentation.
If you want to use the iframe approach instead, you'll first need an HTML document to host inside of the iframe. The iframe document should be loaded for the same origin (protocol + domain) as the host document (cross-document cross-domain stuff is tricky otherwise). With your application, this is probably not an issue.
Host page:
<iframe id="preview" src="preview.html"></iframe>
To make things easier on yourself, this iframe document could load a script with convenience functions for injecting the HTML and CSS from the host.
preview.html:
<html>
<head>
<script src="preview.js"></script>
<style type="text/css" id="page-css"></style>
</head>
<body></body>
</html>
preview.js:
function setHTML(html) {
document.querySelector('body').innerHTML = html;
}
function setCSS(css) {
var stylesheet = document.querySelector('#page-css');
// Empty the stylesheet
while (stylesheet.firstChild) {
stylesheet.removeChild(stylesheet.firstChild);
}
// Inject new CSS
stylesheet.appendChild(document.createTextNode(css));
}
Now, from the host page, you can call these functions whenever your text inputs change:
document.querySelector('#preview').contentWindow.setCSS(someCSS);
This plugin may come in handy: https://github.com/websanova/wJSNova/downloads .
Edited
Insert the text of the rules in one of the existing cssStyleSheets you have.
It will be something like
window.document.styleSheets[0].insertRule("a{color:red;}",window.document.styleSheets[0].cssRules.length)
The first parameter is the rule to insert and the second is the index.
Fiddle
The only problem here is that this will affect all the DOM on the page maybe looking for a way to add the #preview before each css rule to get something like
#preview h1{}
I would like to add a theme support to my single page application. The requirement is that the theme change must be done locally by javascript (no server calls) to be used in offline mode. I use angularjs, so html will be changed in the router.
The only problem that I have, is how to treat css. Is there any js library to help me load css files? Are there any problems involved in that?
EDIT: I have found the following library https://github.com/rgrove/lazyload/ which should do the job of loading css files. The only downside of the library is that the last update of the library is more than one year ago. A more actively developed library would be appreciated.
style elements can be added and removed in JavaScript. Simply create the element and add it to the page to apply the rules therein, and remove the element to remove its rules. You can do the same with link elements referring to external stylesheets, but if you want to be sure to work in offline mode and if the sheet may not have been cached, style elements with inline rules might work better.
Here's an example using a style element:
(function() {
var css = "body { color: green; }";
document.getElementById("theButton").onclick = toggleStyle;
function toggleStyle() {
var style = document.getElementById("styleOne");
if (style) {
// Remove it
style.parentNode.removeChild(style);
}
else {
// Add it
style = document.createElement('style');
style.id = "styleOne";
if (style.styleSheet) {
style.styleSheet.cssText = css;
}
else {
style.appendChild(document.createTextNode(css));
}
document.body.appendChild(style);
}
}
})();
Live Copy | Source
Using a link would be even easier, because you don't have to deal with browser differences around where the style text goes.
If your theme only change the color, what I will do is using different css class to address this issue. Since CSS can be overwrote, you just need to attach themename as a class to parent element, and create corresponding rule for it. I would suggest to put all theme related css rule in a different file, that will be easier to maintain.
like
.themename.cssclassname{
color: red;
}
will trump
.cssclassname{
color: green;
}
And you can use less to create nested rules easily
By doing this, you will have 3 benefits.
All browsers accept this including IE7. (I think IE7 has some problems when you dynamically insert style tag)
All CSS file will be cached.
easy to maintain. (I really don't like mix CSS and JS together too much.)
Hallo All,I have a problem. I have written a very extensive script to change my body-background from a page-specific background-image to an other background-image. For refrence:My 'mypage.html' has a default background of class='image1' defined in the default stylesheet.I have written a script to change this to class='image10' or class='image11', which are defined in the persistent stylesheet. (Believe me, this is the short version, but this part works... well, is going to. No questions here.)My 'otherpage.html' has a default background of class='image2' defined in the default stylesheet and I want to be able to change this as well to the same 'image10' and 'image11' from the persistent stylesheet.Both default backgrounds have multiple differently colored versions in alternate stylesheets... Change the stylesheet and class='image1' links to another version of the image.All this is directed by cookies that are page specific as well. This makes finding a solution quite important, because otherwise I would have to set cookies for every single page. Which I find unacceptable.My question is, do I have to copy/past the whole script to my 'otherpage.html' and change al the 'image1's to 'Image2's or is there a way to javascript something like:
if(HTML = 'otherpage.html') {
(".image1" = ".image2")
}
Excuse my very amateuristic script. I have looked all over, but I wouldn't even know how to search for this... Hope someone can help, otherwise copy/past it is ;)
You can use this little script here
var currentPage = window.location.pathname;
if (currentPage == "/somepage.html") {
// change the body class name
document.getElementsByTagName("body")[0].className = "image2";
}
You can use a switch statement if you have multiple pages to test.
You can control the styles(background and other styles) through the base class which you can set it to body tag of the document or any root container. On page load check the page name and set the class names accordingly.
if(page == "otherPage"){
document.body.className = "image2";
}
Now all the classes falling under image2 will be applied.
I have a two part question.
First, the scenario:
Due to some bizarre issues we've run into in regards to mobile browser support for NOSCRIPT, I'm tasked with coming up with an alternative solution to 'detect' JS. The solution logic is to have two DIVs on the page. One is an error stating you do not have JS and his shown by default. If one has JS, we then want to add a new STYLE block to the HEAD that over-rides the previous CSS and hides the error and instead shows the content.
The sample HTML:
<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
This is the JS I started with:
var styleNode = document.createElement('style');
styleNode.setAttribute("type", "text/css");
styleNode.innerHTML = "#div1 {display: block;} #div2 {display: none;}";
headTag.appendChild(styleNode);
But, I was having problems. Some googling resulting in this description of a security issue that IE can have if you try to insert innerHTML into a created element before placing it in the DOM:
http://karma.nucleuscms.org/item/101
So, I modified the script as such:
var styleNode = document.createElement('style');
styleNode.setAttribute("type", "text/css");
var headTag = document.getElementsByTagName("head")[0];
headTag.appendChild(styleNode);
var aStyleTags = headTag.getElementsByTagName("style");
var justAddedStyleTag = aStyleTags[aStyleTags.length-1];
justAddedStyleTag.innerHTML = "#div1 {display: block;} #div2 {display: none;}";
question 1: is that a valid workaround for the IE issue? Is there a more efficient solution?
question 2: even with the adjustment, the script still does not work in IE. It works fine in Firefox, but in IE 7 I get an "unknown runtime error".
I have a sample of this code up on JSBIN:
http://jsbin.com/ucesi4/4
Anyone know what's going on with IE?
UPDATE:
I stumbled upon this link via google. Note the last comment:
http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
That said, you really should put all
style rules in the HEAD for strict
compliance with XHTML. Doing this can
also be a little tricky because you
cannot use innerHTML to inject into
the HEAD or STYLE element directly.
(Both of these tags are READ ONLY.)
Eep! True? Is FireFox just being overly forgiving? Or is this just a very odd IE quirk?
UPDATE 2:
A bit more background on what we're trying to solve here. We're dealing with mobile devices and some of the antiquated devices a) don't support NOSCRIPT and b) have slow JS engines.
Since they don't support NOSCRIPT, we are by default showing an error, then hiding it via JS if they have it, and presenting them with the proper content. Because of the slow JS engines on these, people see the 'flicker' of the DIV's showing/hiding. This was the proposed solution to handle that, as it would load the CSS before the DIVs were even rendered.
Since it appears to be invalid, the solution will be that on these old devices, we'll use this method (as it seems to work, even if not in IE) and then all other proper browsers will do as suggested...we'll just update the DISPLAY CSS property via inline JS after each DIV is loaded in the DOM.
All that said, I'm still curious as to whether this issue is an IE bug, or if IE is actually adhering to the proper standards by making STYLE a read-only element.
In IE you can use style.styleSheet.cssText:
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) { // IE
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
document.getElementsByTagName('head')[0].appendChild(style);
Try this here: http://jsfiddle.net/QqF77/
See the answer on this question: How to create a <style> tag with Javascript
Don't use innerHTML, use document.createTextNode() and your life will become infinitely better ;)
var styleNode = document.createElement('style');
styleNode.setAttribute("type", "text/css");
var textNode = document.createTextNode("#div1 {display: block;} #div2 {display: none;}");
styleNode.appendChild(textNode);
headTag.appendChild(styleNode);
EDIT:
Since this solution doesn't seem to work for you, I'd abandon it. Instead go for a solution where styles are already defined and where you just disabled/enable styles via javascript if available.
You can do it this way:
<head>
<style>
.jsenabled #div2, #div1 { display: none;}
.jsenabled #div1, #div2 { display: block;}
</style>
<script>
//i know you don't use jQuery, but the solution should still be valid as a concept
//bind to DOM-ready, then set the class jsenabled on the body tag
$(function() {
$(document.body).addClass('jsenabled');
});
</script>
</head>
<body>
<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
</body>
EDIT 2:
If it has to be done prior to DOM ready, you could do something kinda ugly like this:
<head>
<style>
#div2, .show { display: block;}
#div1, .hide { display: none;}
</style>
</head>
<body>
<div class="hide">
<script>document.write('</div><div id="div1">');</script>
div 1 (should be shown if JS enabled)
</div>
<script>document.write('<div class="hide">');</script>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
<script>document.write('</div>');</script>
</body>
Or to keep things simple, you could just do
<head>
<script>document.write('<style>#div1 {display: block;} #div2 {display: none;}</style>');
</head>
<body>
<div id="div1">div 1 (should be shown if JS enabled)</div>
<div id="div2">div 2 (should be hidden if JS enabled)</div>
</body>
Best practice is to put all the <link for CSS into the <head, and most <script at tne very end of the <body (except short fragments of <script that should execute ASAP should go in the <head). Both the standard and browsers allow you to do silly things, but just because it's acceptable doesn't mean it's a good idea.
Rather than go through all the rigamarole of creating a Style node and of manipulating the DOM (which just provide more opportunities for something to go wrong), I recommend a much simpler solution. Hard code as much as you can into your document (and style sheet?) in advance once (rather than creating things on the fly every time). Here's a rough example:
<body ...
...
<div id="warning" style="display: block;">
JS is required for this site, but isn't available ...
</div>
<div id="message" style="display: none;">
JS is available
</div>
...
<script ...
var warningEl = document.getElementById('warning');
warningEl.style.display = 'none';
var messageEl = document.getElementById('message');
messageEl.style.display = 'block';
</script ...
This should work reasonably well most of the time (it will certainly work in more browsers than what you tried to do initially). However, any attempt to change the DOM in any way before the page is initially displayed to the user is not guaranteed to work (in other words neither your way nor the example above will always work in all cases). The earlier you run your Javascript, the more likely DOM operations (including getElementById) may fail. And the later you run your Javascript, the more likely the user will notice a perceptible "flicker" of their display. So you're presented with a tradeoff choice between wide compatibility and noticeable flicker.
You can wait until the DOM is guaranteed to be fully ready before you run your Javascript ("ready" in jQuery, or addEventListener 'domcontextloaded', or even addEventListener 'load'). This is guaranteed to function correctly in all cases. But it will flicker (perhaps quite badly) in many cases.
The only way I know (but I hope somebody else knows more:-) to avoid entirely the possibility of flicker is to put in the <head a fragment of Javascript that changes window.location but does nothing else. (No references to the DOM, which are usually made obvious by the word "document" somewhere in the code.) The net effect if JS is available will be an immediate reload of a different page before much of anything is shown to the user. The initial page can contain your warning, and the new page the real stuff with no warning.
Even this method has some disadvantages though: First, the double download takes extra bandwidth and delays user visibility a little. This won't matter on typical desktops. But on handhelds it may not be acceptable. And second, it will raise havoc with SEO. The second page -that's supposed to be invisible and only accessed from the first page- may show up independently in webdexes so users can easily access it directly (you may be able to "fix" this with clever use of "canonical" and/or "meta...robots"). And the SERP of the initial page may fall precipitously when its only content is the warning message.