One way would be to check if there is a .shadowRoot property on an element, however I need to return a boolean before the page is rendered.
One simple feature test would be:
if (document.head.createShadowRoot || document.head.attachShadow) {
// I can shadow DOM
} else {
// I can't
}
This will work even if you include the script in the head section and assumes no malicious scripts were added prior to yours (a safe assumption).
Currently, Chrome, Opera, and derived browsers (like Android browsers) support it.
For more information, visit: https://caniuse.com/#feat=shadowdomv1 and http://caniuse.com/#feat=shadowdom
Related
I have the following code:
someSelector:after {
content: attr('data-some-data');
/* ... */
}
Everything works fine (the value is reflected on the screen) until I change this attribute to something else:
document.querySelector('someSelector').dataset.someData = 'some other value';
The content doesn't get updated on the screen but when I open the DOM explorer I can clearly see, that the value of the attribute is indeed updated.
I tried to set this manually through the browser console but also with no success.
Everything works correctly in other browsers but of course in IE... You know...
The question
Is it possible to force an update of this value so it will be reflected on the screen when changed?
IE11 for some unknown reason does not redraw DOM when you modify element dataset.
But if you have to support IE11 use Element.setAttribute method like so:
document.querySelector('someSelector').setAttribute('data-some-data', 'some other value');
DOM will be redrawn and the pseudoelement content should be updated.
Modern browsers automatically combine some letters, most commonly 'f' and 'i' to one single character called a ligature. This often optimizes legibility (i.e. easier to read), however sometimes this might not be what a designer wants.
Personally, I had this issue only in Chrome (Version 53.0.2785.101), I, although I cannot be sure, I believe this issue persists in all other versions of Chrome.
Chrome
f and i is combined multiple times
Edge
IE11
In this case I was looking for a way to turn it off.
As it turns out, it's definitely possible, it just required some digging. As mentioned on MDN, you can turn off common ligatures:
font-feature-settings: "liga" 0;
This, however, is done by using an obscure css property. Instead, you should use font-variant-ligatures, like so:
font-variant-ligatures: none;
These two properties does the exact same thing, however, the latter one is recommended one.
MDN:
Note: Whenever possible, Web authors should use the font-variant shorthand property or an associated longhand property, font-variant-ligatures, font-variant-caps, font-variant-east-asian, font-variant-alternates, font-variant-numeric or font-variant-position.
This property is a low-level feature designed to handle special cases where no other way to enable or access an OpenType font feature exists.
In particular, this CSS property shouldn't be used to enable small caps.
I encountered a similar problem and was directed here by Google.
I never want ligatures on any webpage.
(When I print a webpage to PDF and use the text-to-speech engine on my PDF reader, it skips speaking the ligatures.)
Here is one solution that works for me:
Open the webpage on Chrome/linux (may work on other desktop OSes too).
Install the StyleBot extension of Google Chrome. Then, in its options, click "styles" and then "edit global stylesheet". Enter the following (based on the answer of #AwesomeGuy).
body {
font-variant-ligatures: none;
font-feature-settings: "liga" 0;
}
Click "enable global stylesheet". Voila, Chrome never seems to render ligatures again (it renders the characters separately).
Also, when I ask Chrome to print web pages to PDFs, characters are rendered separately.
Add this as a bookmark and click once when printing.
javascript: void(function () {
var css = `
* {
font-variant-ligatures: none!important;
font-feature-settings: "liga" 0!important;
}
`;
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet) {
/*This is required for IE8 and below.*/
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
head.appendChild(style);
/*It is not necessary to set a delay.*/
setTimeout(function () {
window.print();
}, 2000);
})()
Adding Javascript Applets to Chrome’s Bookmarks
https://clicknathan.com/2010/07/12/how-to-add-javascript-applets-to-as-google-chrome-bookmarks/
Open a New Tab in Chrome. Command+T on a Mac, Ctrl+T on a Windows.
Google Toolbar as seen in Chrome's New TabRight click on the Bookmarks Toolbar. It’s a gray colored box like the one pictured here.
Select “Add Page” from the contextual menu that appears.
Give the Bookmark a name. You could Google “Baby Names” if you can’t come up with one. I like Shepherd or Samson or even Samsonite if you have aspirations of a career in luggage design, sales or airport security.
Paste the Javascript applet into the URL field.
Save that son of a gun and you’re on your way to finishing this tutorial!
Let's say for example I'm going through my stylesheet but I can't remember what element a certain CSS selector affects.
Is there any method, tool, or anything that I could do/use to find out what exactly it is affecting?
Thanks!
I just opened up a random bootstrap template site and did what you where asking for.
Open up your chrome browser (I prefer this as I feel this is easy to debug both Jquery and css) and Press F12, you will get a developer window as in the image.
Switch to the console tab.
Use Jquery selector to select all
the intended elements (you can use the same css selector here too
but just place them inside $('')) Eg: $('.tab-content') I am trying to find out all the elements with the class tab-content
The result is all the elements
of that selector.
NOTE: This appraoch woud require you to have Jquery loaded into your page. Else the script will throw an error saying $ is not defind.
In addition to using your browser's development tools, there are two easy ways to do it that should work in almost any browser (no matter how bad the developer environment).
Visually
Temporarily set a border or background color for the selector, like:
border: 1px solid red;
Or:
background: red;
This makes it very easy to find the affected elements.
Programmatically
On the JavaScript console, use:
// Replace with something that prints the relevant details
var stringify = function(element) { return element.innerHTML; };
// Iterate over all affected elements and print relevant info
var affectedElements = document.querySelectorAll('.your .selector');
var len = affectedElements.length;
console.log('Elements affected: ' + len);
for (var i = 0; i < len; i++) {
var affectedElement = affectedElements[i];
console.log(
'Element ' + (i+1) + ':\n' +
stringify(affectedElement) + '\n\n');
}
The inspection of elements feature of the browser is meant for the purpose you want.
1.Open up the index file in any browser(preferably Mozilla Developer edition),
2.Right click and Inspect element,
3.Then open the compiled stylesheet. Find out the style element you want to check the effect of.
4. Go back to inspection, remove/add CSS properties and see the effect in real time.
The other way is to use Adobe brackets. It's live preview feature will highlight the section that involves the code snippet, you point your cursor to.
What are good ways to detect whether a style sheet has loaded using vanilla JavaScript? I understand they do not have the same load event that images and scripts fire.
Loading as packed into a .js file (like with WebPack 'loaders') is not an option.
2022 update: All major browsers have now supported onload= on <link rel=stylesheet> tags for years, so that would be the obvious way to detect when CSS has loaded. Not also that external stylesheets in the head are blocking during page load, but can be added later with JS to make them asynchronous. It’s that scenario in which my question is relevant.
Test page: https://alanhogan.com/files/async-css/head-async-test-with-js.html
<link> elements have load and error events, but they are garanteed only for Chrome, Firefox and Opera. If you don't need to support IE or Safari, I think this is just enough:
<link rel="stylesheet" href="some_style.css" onload="anounceReady()">
EDIT: Just tested with IE11 and IE8, onload is supported but onerror isn't. I have no Mac at hand so I don't know how Safari handles them.
If you are going to support browsers don't have load event for <link> elements, or very old Chrome/Firefox, there is a commonly used easy dirty but working solution. Add a piece of probing rule set at the end of your CSS file, and detect the computed style of a certain probing element (usually invisible) via JavaScript.
HTML:
<div id="probe"></div>
CSS:
#probe {
position: absolute;
z-index: -1000;
}
JavaScript:
var probeStyle = getComputedStyle(document.getElementById('probe'));
probeStyle.zIndex; // expect "-1000" after CSS is loaded
Something like this:
function checkSheetLoaded (urlSpec) {
var ss = document.styleSheets;
for (var ii = 0, max = ss.length; ii < max; ii++) {
if (ss[ii].href.indexOf(urlSpec) >=0)
return true;
}
return false;
}
checkSheetLoaded('foo/bar.css');
Basically iterates over the stylesheet collection looking for a string match.
Is it possible to create a new property in CSS? For example, say you're developing a control that displays a photo and you want to add a property to css to control what style frame to have around the photo. Something like:
#myphoto { frame-style: fancy }
Is there some way to do this in a cross browser compatible manner, and how would you define whether the style inherits or not?
EDIT: It's a custom control - your JS code would deal with the style - I'm not expecting the browser to magically know what to do. I want the user to be able to style the control with CSS instead of JS.
Sure, why not. Check this out as an example: http://bililite.com/blog/2009/01/16/jquery-css-parser/
You may also be able to get away with using CSS classes instead of properties. Not sure if that works for what you're doing.
You can't. Browsers interpret CSS based on how their layout engines are coded to do so.
Unless you took an existing open source engine like WebKit or Gecko, added custom code to handle your custom CSS and made a browser that used your customized layout engine. But then only your implementation would understand your custom CSS.
Re your edit: it'd depend on whether you're able to read that style somehow. Typically browsers just instantly discard any properties they don't recognize, and CSS is not normally reachable by JavaScript because CSS code is not part of the DOM.
Or you could look at Jordan's answer.
If you'd prefer a straight JavaScript solution that uses no JS libraries, you could use the query string of a background-image to keep "custom properties" inside your CSS.
HTML
<div id="foo">hello</div>
CSS
#foo {
background: url('images/spacer.gif?bar=411');
}
JavaScript
getCustomCSSProperty('foo', 'bar');
Supporting JavaScript Functions
function getCustomCSSProperty(elId, propName)
{
var obj = document.getElementById(elId);
var bi = obj.currentStyle ? obj.currentStyle.backgroundImage : document.defaultView.getComputedStyle(obj, null).getPropertyValue('background-image');
var biurl = RegExp('url\\(["\\\']?([^"\\\']+)["\\\']?\\)').exec(bi);
return getParameterByName(propName, biurl[1]);
}
function getParameterByName(name, qs) {
var match = RegExp('[?&]' + name + '=([^&]*)').exec(qs);
return match && decodeURIComponent(match[1].replace(/\+/g, ' '));
}
Demo:
http://jsfiddle.net/t2DYk/1/
Explanation:
http://refactorer.blogspot.com/2011/08/faking-custom-css-properties.html
I've tested the solution in IE 5.5-9, Chrome, Firefox, Opera, and Safari.