CSS style element optimization logic - html

Problem
Some process is generating HTML files (more than one) with style elements (containing CSS) that may appear anywhere (even outside head elements). Please ignore for a moment that this is non-standard, in this case it is intended (and not a bug).
Objective
The target is to post-process the aforementioned HTML files to make it valid or more performant.
The first step is to "pull" up all these style elements into the head element (to make the HTML valid). This is very easy to do (I'm using a DOM manipulation library).
The next step is extract common CSS into a shared external CSS file. This part is where it gets tricky: it's possible that by extracting all shared styles, either the non-shared or the external ones might overwrite each other (hopefully the example below is more clear).
After step 1
(assume all styles have been moved to head in the same order)
test1.html
..
<head>
<style> h1 { color: red } </style>
<style> h2 { color: blue } </style>
<style> h3 { color: green } </style>
</head>
..
test2.html
..
<head>
<style> h1 { color: red } </style>
<style> h2 { color: purple } h3 { color: yellow } </style>
<style> h3 { color: green } </style>
<!-- NOTE: h3 will be effectively green -->
</head>
..
After step 2
shared.css
h1 { color: red }
h3 { color: green }
test1.html
..
<head>
<link rel="stylesheet" href="shared.css">
<style> h2 { color: blue } </style>
</head>
..
test2.html
..
<head>
<link rel="stylesheet" href="shared.css">
<style> h2 { color: purple } h3 { color: yellow } </style>
<!-- NOTE: h3 will now be yellow, but it should have been green -->
</head>
..
I hope the example makes sense. The question is, is there any good way to avoid mangling up the rules' order while still being able to optimise it?
I can see these two solutions so far:
only extract shared CSS until the first block that is not common anymore (e.g. in the example above, only h1 will be shared).
pass the entire documents' CSS through a parser that generates the effective CSS, somehow figuring out and removing declarations that have been overridden while also keeping the overriding ones unshared.

Related

Is there any way to have a customizable class element in html that a css file can extract custom values from?

For example, say I want to create text in HTML with the color blue and a size of 13px.
Is there any way I can do something like:
<h1 class = "blue 13px">Hallo</h1>
And then use CSS to make it blue and 13 px without doing:
.blue 13px {
color: blue;
font-size: 13px;
}
Instead of using CSS classes, you could use inline styling in your HTML elements:
<h1 style="color: blue; font-size: 13px;">Hallo</h1>
Because of its poor maintenance and reuse qualities, this styling strategy is generally not advisable though. Use with caution. ;)
Also note that the CSS code that you provide in your question is invalid. CSS class names have to be valid CSS identifiers. This would be more correct:
<h1 class="blue-13px">Hallo</h1>
.blue-13px {
color: blue;
font-size: 13px;
}
And also note that you can include CSS rules inside your HTML page as well (without using a separate CSS file):
<style>
.blue-13px {
color: blue;
font-size: 13px;
}
</style>
<h1 class="blue-13px">Hallo</h1>
CSS
:root
{
--css_h1_color: rgba(204,204,204,.2);
}
h1 {color: var(--css_h1_color);}
JavaScript
getComputedStyle(document.documentElement).getPropertyValue('--css_h1_color');

`hover` pseudo-class not working

This is my css file, till now I have made a simple navigation bar.
But the point is for my <a> elements in the navigation bar, when I try to style them both in case a and a:hover they work only when I give !important. What is happening. Is there a specificity issue ?
#import url('http://fonts.googleapis.com/css?family=Lato');
.navbar {
background-color: #b6b5b4;
border-style: solid;
}
.container {
background-color: #bfbfbf;
}
body {
font-family: Lato;
}
a {
color: black !important;
font-weight: bold;
}
.navbar-right {
background-color: #aeaeae;
}
a:hover {
background-color: #dfdfdf !important;
}
I am new to css and html.
You imported Bootstrap, which has default CSS styling. What you're basically doing, is trying to overwrite those styles. However, Bootstrap seems to be taking precedence over your CSS (probably due to the order of the imports in your HTML file), thus requiring !important. The !important tag makes sure that, that particular style cannot be overwritten or, is always displayed over others.
<link rel="stylesheet" type="text/css" href="main.css">
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
If your ordering is like this, Bootstrap styling will be displayed, unless you use !important.
What is happening is parent divs like .container (may be, dont have your html structure) is having background-color css. This css will override the hover css on child <a> element. !important keyword is made only for this purpose. It does not allow other styles to override itself. Thats why you should use !important keyword in such cases.
a:hover { background: #dfdfdf !important;}
use this one
You have default css file with styles with its nesting! quick fix for this issue: assign class for <a> with your styles!
a.my-class {
color: black;
font-weight: bold;
}
a.my-class:hover {
background-color: #dfdfdf;
}
Yes, If u give like this
a {
background-color: black !important;
}
!important overrides the hover state styles also.
a {
background-color: dfdfdf;
}
doesn't work.
give your style like this
a {
background-color: black;
}
//remove !important
remove !important from <a> tag. Hover state works normally.
Let me know if u get any errors.

Why is style *{display:*} included in the HTML body?

When I add such CSS into <style> tags:
* {
display:block;
}
It is never interpreted correctly. Instead, what do I see? Somehow everything inside <style> becomes the part of html body. E.g.:
* {
display:block;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
This happens anywhere. For the first time, I thought this is the problem with StackSnippets. (i.e. the live demo for Stack Overflow, the one I've provided above), but then I checked with code pen. Then with jsfiddle. Then I've gone ahead and made a file on my server, giving it all contents I inserted in the snippet above.
The outcome is always the same. The CSS gets included in the html, though it is applied. (the only fix is to create a stylesheet and include it using <link>)
The most interesting thing, is, that it seem to happen only with display:*. E.g., the following works:
* {
color:green;
background:red;
border:2px solid orange;
border-radius:5px;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
But once I put in the styles of the last snippet display:*, the styles are, again, magically included in HTML.
* {
color:green;
background:red;
border:2px solid orange;
border-radius:5px;
display:inline-block;
}
<p>paragraph</p>
<phrase>phrase</phrase>
<pet>pet</pet>
Why does it happen?
It's styling the <head> element and everything in it, including the very <style> element your CSS resides in, because the CSS appears as character data within the <style> element. A <link> element on the other hand doesn't have any content — it points to a separate resource altogether, so there is nothing inside the element itself to be displayed.
Most browsers implement <head> as display: none (and some propagate that value to every descendant), which you are able to override by targeting them with a display style. The rest of the properties are still applied to <head> and its descendants regardless of whether you do this, but without it, they simply won't show up in your page so you don't really see it happening. That's really all there is to it — there isn't anything else that's special about <head> or its related elements.
In other words, as far as CSS is concerned, the following (yes, a <style> element with a style attribute...):
<style style="display: block; font-family: monospace">
p { color: red; }
</style>
Is no different from this:
<code style="display: block; font-family: monospace">
p { color: red; }
</code>

Apply <style> rules to another element instead

I have a <style> element that applies some global styles, like A { color: red } as opposed to my stylesheet that styles A { color: green } (purely as an example).
How can I modify all of the styling in my <style> element so that are "contained" and only apply the styling to children of a parent element I specify.
A { color: red } becomes #myelem A { color: red }
.myclass { display: none; } becomes #myelem .myclass { display: none }
Would I have to find the <style> element, parse the contents, replace each selector then update the element contents with it fixed?
Is there an alternative to modifying the contents of my <style> element?
Why am I doing this? I have HTML that is stored in a database that I want to edit (this is a CMS). The HTML can contain <style> elements, and I cannot trust who writes the CSS to write it in scope. I could prevent users from using the <style> element, but I'd rather not. I have no control over the original CSS. Only what I get back in my server/clientside code.
If all else fails, I might have to load it into an iFrame... :(
Ooooooo Firefox supportes <style scoped> which only applies to the parent where the <style> element is located in the DOM. Too bad it's not supported in any other browser. :(
As you mentioned, you can use:
<style scoped>
...
</style>
Although it is only supported natively in Firefox, you can use this jQuery polyfill to get it to work in other browsers.
Use the child selector:
#yourElement > a { color: green; }
JQuery:
$( "parent_type > children_type" ).css("param","value");
example
$( "#myid > div" ).css("display","none");
here's a link
JSFiddle

un-style some component

i am using a definitive style for my tags. now there is one tag that i do not wish to appear that way. how do i do it?
Give that one tag an ID, and then make a style for that specific ID. It will override the style you set for the "a" tags.
First, figure out the class or id of the element you want to change the style of using tools like firebug. Once you have found its class or id, search for it in the style sheet and modify the style as you like. If it still does not work, try appending the !important to your style, for example:
.myelement
{
color: #ff0000 !important;
font-size: 14px !important;
}
The !important will override any pre-defined styles.
You can't always reliably "unstyle" an element. For some style properties setting the value to auto, default or none will work:
<!doctype html>
<html lang="en">
<head>
<title>Test</title>
<style>
a { background: pink; }
a.normal { background: none; }
</style>
</head>
<body>
<p>link1
<p>link2
<p>link3
</body>
</html>
But not for example color. Replace background in above example by color. It won't work. You'll really need to force the color yourself, e.g. color: blue.