How can I insert CSS styles inside <body> independent of specific elements? - html

Traditionally, you can add CSS in three ways:
External CSS via <link rel="stylesheet" href="foo.css">
Internal CSS via <style> h1 { ... } in the <head> element
Inline CSS via the style="..." attribute on specific elements
Inline CSS has the drawback that I can't use CSS classes, which is something I need to do. Is there a way to define internal CSS (e.g. a <style></style> fragment in the <body> element?
This would be much easier for me because I could create a self-contained HTML snippet with a method in my server code. This kind of method is necessary because I don't control the <head> section. It is owned by a commercial product. I can only insert content inside the <body>.
Example:
<div>
<style>
.myclass {...}
</style>
<div class="myclass">...</div>
</div>
Related: https://htmx.org/essays/locality-of-behaviour/
I have seen other websites (like https://amazon.com) where they appear to have several style tags inside the <body>.
There is a huge gap between theory and practice. Many sites use <style> in the body.
The editors decided against it. But maybe there will be a change in the future: https://github.com/whatwg/html/issues/1605

Under the premise, you don't care about invalid HTML in relation of <style> inside <body> (which is not that uncommon), you can assign unique identifier i.e.:
<style>
.my-class-1 {
color: gold;
}
</style>
<div class="my-class-1">Fragment Content</div>
<style>
.my-class-2 {
color: tomato;
}
</style>
<div class="my-class-2">Fragment Content</div>
<div class="my-fragment-1">
<style>
.my-fragment-1 .my-class {
color: teal;
}
</style>
<div class="my-class">Fragment Content</div>
</div>
<div class="my-fragment-2">
<style>
.my-fragment-2 .my-class {
color: hotpink;
}
</style>
<div class="my-class">Fragment Content</div>
</div>
<style id="my-style-1">
#my-style-1 + div {
color: orangered;
}
</style>
<div>Fragment Content</div>
<style id="my-style-2">
#my-style-2 + div {
color: indigo;
}
</style>
<div>Fragment Content</div>

the simpler answer to your question is "Yes" and I'll elaborate on this with several examples below. A <style> tag will work wherever you place it within either the <head> or the <body>.
A style tag placed in the <body> tag technically does violate HTML syntax rules, it's surprisingly common in practice, even among some larger corporations.
There are several different methods for including <body>-level <style> tags in your project.
1. Pure HTML <style> tags (the static method)
If you have all the styles you need already written up and there are no dynamic pieces needed, you can simply write those styles into a <style> tag statically and include those in the code, as seen in this example below:
<html>
<head></head>
<body>
<div class="custom-widget">
<h1>This is a title</h1>
<p>This is some text.</p>
<style>
.custom-widget {
display: block;
padding: 20px;
border: 5px double red;
}
.custom-widget h1 {
text-transform: uppercase;
}
.custom-widget h1::first-letter {
font-size: 150%;
}
.custom-widget p {
font-style: italic;
}
</style>
</div>
</body>
</html>
2. Writing the styles into a <style> tag as text using JavaScript
If you need to load the styles into your <style> tag dynamically and you simply need plain text styles that you will not need to change much after creating them. You can create the <style> block and then inject the CSS styles as plain text as desired, as seen in this example below:
const counter = document.getElementById('counter');
let count = +counter.dataset.count;
const customWidgetStyle = document.querySelector('.custom-widget style'),
countdown = setInterval(() => {
if (count--) {
counter.innerText = `Importing CSS in ${count}…`;
} else {
clearInterval(countdown);
counter.remove();
customWidgetStyle.innerHTML = `
.custom-widget {
display: block;
padding: 20px;
border: 5px double red;
}
.custom-widget h1 {
text-transform: uppercase;
}
.custom-widget h1::first-letter {
font-size: 150%;
}
.custom-widget p {
font-style: italic;
}
`;
}
}, 1000);
<html>
<head></head>
<body>
<div class="custom-widget">
<h1>This is a title</h1>
<p>This is some text.</p>
<style></style>
</div>
<span id="counter" data-count="3">Importing CSS in 3…</span>
</body>
</html>
3. Creating cssRules styles into a <style> tag using the JavaScript CSSStyleSheet.insertRule() method
If you need even more flexibility with how you add your styles, you can use the CSSStyleSheet.insertRule() (MDN docs), which will dynamically allow you to add and manage the styles more granularly. This may be overkill for your specific need but there's a lot of power, flexibility, and control when working with the CSSOM.
Here is an example of this method, in which I use an addStylesheetRules function example defined on the MDN docs page for insertRule under the heading Examples, here:
const addStylesheetRules = (rules, stylesheet) => {
if (stylesheet === undefined) {
const style = document.createElement('style');
stylesheet = style.sheet;
document.head.appendChild(style);
}
for (let i = 0; i < rules.length; i++) {
let j = 1,
propStr = '';
rule = rules[i];
const selector = rule[0];
if (Array.isArray(rule[1][0])) {
rule = rule[1];
j = 0;
}
for (let pl = rule.length; j < pl; j++) {
const prop = rule[j];
propStr += prop[0] + ': ' + prop[1] + (prop[2] ? ' !important' : '') + ';\n';
}
stylesheet.insertRule(selector + '{' + propStr + '}', stylesheet.cssRules.length);
}
}
const customWidget = document.querySelector('.custom-widget'),
customWidgetStyleTag = document.createElement('style');
customWidget.appendChild(customWidgetStyleTag);
const customWidgetStylesheet = customWidgetStyleTag.sheet;
addStylesheetRules([
['.custom-widget',
['display', 'block'],
['padding', '20px'],
['border', '5px double red']
],
['.custom-widget h1',
['text-transform', 'uppercase']
],
['.custom-widget h1::first-letter',
['font-size', '150%']
],
['.custom-widget p',
['font-style', 'italic']
]
], customWidgetStylesheet);
<html>
<head></head>
<body>
<div class="custom-widget">
<h1>This is a title</h1>
<p>This is some text.</p>
</div>
</body>
</html>
Please let me know if there is any more context I can add to better answer your question.

It is going to work in html5, even if it's regarded as invalid in html4.
I have an example from where I work now.
We are adding a slideshow for some books in a library catalogue and because this is done with a plugin the only possible way to style this is to include a <style> block with the html, as this plugin doesn't and shouldn't have access to <head> of the CMS it is designed for.
However, this solution is a last resort because of limitations of how the CMS is built and should be avoided.

Couldn't you target the head element with Javascript and insert a style programmatically?
<script>
var head = document.querySelector('head')[0];
var css = 'div { background: red; }',
var style = document.createElement('style');
style.appendChild(document.createTextNode(css));
head.appendChild(style) ;
</script>

As far as I can understand from the description you gave, you don't have the access to the <head>...</head> element, but you are free to edit the body. Also, you want to use CSS3 Classes, but with inline CSS, you can't.
I can't find a way in pure HTML/CSS, so I suggest you to use JQuery.
<script async src="https://cdn.statically.io/libs/jquery/3.6.0/jquery.min.js" />
<script>$('head').append('<style>/*Your styles here*/</style></script>');
Now, add classes to the html elements and edit the content between the <style /> tag. Also, place this script at the end of <body> so that you can avoid the probable weird problems caused by placing this in between. XD
But remember, this will change the head after the user has loaded the page. So, theoretically, the users will first see an ugly html page without styles, then styles will be loaded and they'd see the page with styles.For more explanation, check out the official documentation: https://api.jquery.com/append/

Your example should work. I work with WordPress using custom html where all the custom code goes into a <body> tag, and styling like so should work within each page (added more divs just to show an example that one style tag can hold classes for all divs within a div):
<div>
<style>
.className { ... }
.classNameTwo{ ... }
.classNameThree{ ... }
</style>
<div class="className"></div>
<div class="classNameTwo">
<div class="classNameThree"></div>
</div>
</div>

Related

CSS scaling and removing whitespace

I'm building a website that uses images which must all be scaled down by a consistent factor (0.25). Like others have pointed out here and here, scaling is an operation that is done after the page elements are rendered, resulting in whitespace surrounding the scaled image. I need to get rid of that extra space.
I've read every solution and still can't figure this out. I'm totally fine with a javascript solution—which I still can't figure out—but I can't help but feel there is an alternative to using the scaling element and bypassing javascript altogether.
I could scale all of the original images down using imagemagick, but that's a last resort for a number of reasons.
<!DOCTYPE html>
<html>
<head>
<style>
.image-container {
background: #555;
}
img {
display: block;
transform: scale(0.25);
}
</style>
</head>
<body>
<p>Here's my first paragraph.</p>
<div class="image-container">
<img src="https://live.staticflickr.com/65535/51806458206_1e7ba12389_o.png"><img>
<img src="https://live.staticflickr.com/65535/51805498867_57abd12b23_o.png"><img>
</div>
<p>Here my second paragraph</p>
</body>
</html>
Here's a fiddle: https://jsfiddle.net/drfk7xz9/31/. Thank you in advance 🙏
Figured it out (with javascript)
window.onload = function () {
resizeImages();
};
function resizeImages() {
var images = document.querySelectorAll("figure > img");
var originalWidth = 0;
for (var i = 0; i < images.length; i++) {
originalWidth = images[i].naturalWidth;
images[i].style.width = (originalWidth * 0.25) + "px";
}
}

CSS - Reset causing Error with my other tags

I am making a hangman game. And I am working on styling everything. I am including CSS reset in my HTML and I think it is causing my tags to error out. Like my H1 tag isn't working now. Any thoughts?
The H1 tag should make my text big and bold. However that is not working. The linked stylesheet I am using is empty right now. When I remove the CSS Reset link the H1 then works correctly.
<!DOCTYPE html>
<html>
<head>
<title>Hangman</title>
<link rel="stylesheet" type="text/css" href="assets/css/reset.css">
<link rel="stylesheet" type="text/css" href="assets/css/style.css">
</head>
<body>
<div class="container" id="gamebox">
<h1>Hang-Person</h1>
</div>
</body>
<script src="assets/javascript/game.js"></script>
</html>
The last script tag is outside the body tag. It should be inside
Be aware to not repeat the same properties for each object in CSS.
Example:
In reset.css:
body {
margin: 0;
text-align: center;
}
And in style.css:
body {
margin: 20px;
text-align: justify;
}
It might cause the browser to get confused, I recommend you to do CSS reset in only one of your stylesheets. You can do it in the other one as well, but it won't be as efficient.
Here you have the universal CSS reset code:
* {
margin: 0;
padding: 0;
}
After this, you can specify the margin or padding to every element, although it violates the DRY (Don't Repeat Yourself) principle.
CSS Working example:
* {
margin: 0;
padding: 0;
}
.object1 {
padding: 70px;
}
It would be more helpful if you post the CSS code for better answers.
Last but not least, the last <script src="assets/javascript/game.js"></script> tag should be inside the body tag.
EDIT: try with the universal CSS reset code and keep the linked stylesheet.

Is it possible to style an html element, so that it won't 'hurt' inner styles

I'm building some sort of framework where the content of the page can be edited with ContentTools. A requirement of ContentTools is that the regions must be parents.
If you try this:
<h1 data-editable data-name="heading">Content</h1>
It wont work as a region has to contain editable block level elements. A way around this is to wrap the tag like so:
<div data-editable data-name="heading">
<h1>Content</h1>
</div>
But I just want to make the text editable, so I automatically wrapped the inner elements in a div. This works but it affects the styles.
Is there a way to make a div 'transparent', so it will inherit all styles?
I tried the following code.
To be clear: In this example I don't write the h1 css, so i have no influence over which styles are used.
$("[data-editable]").wrapInner("<div class='innerWrap'></div>");
/* example h1 css, could be anything */
body > h1{
font-size: 40px;
color: red;
font-family: sans-serif;
border: 3px solid green;
background-color: blue;
padding: 5px;
}
.innerWrap{
all: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 data-editable data-name="heading">Content</h1>
As you can see some things work. But things like a border will double.
It has to be no difference with or without the innerWrap.
Is it possible to do this with css? It has to work on every css property.
I think you need to wrap the h1 with a div not div with h1.
for eg. .wrapInner() will produce something like
<h1 data-editable="" data-name="heading">
<div class="innerWrap">Content</div>
</h1>
But what you want is
<div data-editable data-name="heading">
<h1>Content</h1>
</div>
So please try with .wrap() instead of .wrapInner()
$("[data-editable]").wrap("<div class='innerWrap'></div>");
h1{
font-size: 40px;
color: red;
font-family: sans-serif;
border: 3px solid green;
background-color: blue;
padding: 5px;
}
.innerWrap{
all: inherit;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 data-editable data-name="heading">Content</h1>
.innerWrap{
all: inherit; /* remove it*/
}
As a default behaviour, if you not specify css props for ".innerWrap" it will look same as parent only
The ability to make an individual element editable standalone as opposed to as part of a collection (e.g in a region) is currently being worked on: https://github.com/GetmeUK/ContentTools/issues/79
There is however a short-term imperfect approach you could try, first change you're HTML as follows:
<h1 data-editable data-name="heading">
<span data-inline data-ce-tag="h1">Content</span>
</h1>
This will make the h1 tag the region and tell ContentTools/Edit to treat the inner span element as a h1 (text) element (thanks to the data-ce-tag).
But the next problem is that if the user hit's return you'll end up with a new paragraph tag inside of your h1 - which we don't want. This is where the data-inline attribute comes in, we need to listen for mount events and if the element mounted has the data-inline attribute we'll modify its behaviour so it can't do certain things which might produce undesirable events:
ContentEdit.Root.get().bind('mount', function(elem) {
// We're only interested in elements that are marked as inline
if (elem.attr('data-inline') === undefined) {
return;
}
// Change the default behaviour of the element
elem.can('drag', false);
elem.can('drop', false);
elem.can('remove', false);
elem.can('spawn', false);
});
You can find out more about modifying behaviours here, along with their current limitations here.

Is it possible using css to access anchor tag's text?

Following is my HTML
Branding
Is it possible to access using CSS to access anchor tag's text?
Something like this is what I want? The html is dynamically generated, so please don't mention to have id's or to have any classes.
a[text='Branding']
{
}
People already told you that you CAN'T select text in CSS. But there's some workaround in my opinion.
I don't know what you want to do, possibly a bad thing, but if I were you I'd take this bad practice:
/*First you hide the text*/
a {
font-size: 0; /* hide text */
text-decoration: none !important; /* get rid of that awful underline */
}
/* then you insert a new element using :before */
a:before {
content: 'Branding'; /* This is the text you want for the new element */
color: #333;
font-size: 15px; /* Bring back the text inside the anchor for this new element */
font: 24px sans-serif;
}
fiddle: http://jsfiddle.net/tsu7z546/
In case you want to try out jQuery:
$(document).ready(function(){
var brandingAnchor = $('a:contains("Branding")');
brandingAnchor.hide();
});
Remember! Every time you write jQuery code, you must have already called jQuery library on your page, just like this:
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
</body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
//Your jQuery code goes HERE, just below the library
$(document).ready(function(){
var brandingAnchor = $('a:contains("Branding")');
brandingAnchor.hide();
});
</script>

How can I use the surrounding page's style for a link, in a custom element?

I have a custom <my-header> element that generates a link in shadow dom, which I'd like to have styled the same as the other links in the surrounding page. The old applyAuthorStyles attribute was a decent way to accomplish that, although it had its own problems. Now that applyAuthorStyles has been removed, the option I see is to have embedders define their global styles as:
a, * ^ a { color: green; }
and so on, which intrudes into the styles of elements that don't want the page's styles.
Is there a better way to do this?
I have some sample code at http://jsbin.com/yusox/1/edit and below. You'll only see the inconsistency if your browser has native Shadow DOM turned on (chrome://flags/#enable-experimental-web-platform-features in Chrome).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/polymer/0.1.4/platform.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/polymer/0.1.4/polymer.js"></script>
<title>Test</title>
<style>
body {max-width: 50ch;}
a { color: green; text-decoration:none; border-bottom: 1px blue dashed ; }
a:visited { color: darkgreen;}
</style>
<polymer-element name="my-header" noscript attributes="sec_num">
<template>
<style>
:host { display: block; }
header { font-weight: bold; margin: 20px 0; }
header::after { clear:both; display: block; content: " "; height: 0 }
</style>
<header>
<span class="section-number">{{sec_num}}</span>
<content></content>
<span style="float:right">[{{id}}]</span>
</header>
</template>
</polymer-element>
</head>
<body>
<my-header id="first.section" sec_num="1.2">Foo Bar Baz</my-header>
Polymer
</body>
</html>
intrudes into the styles of elements that don't want the page's styles.
Yes, intrusion will happen if you use *, so instead drive the style for your specific element:
a, my-header ^ a, body ^^ my-header ^ a { .. }
Fwiw, I don't think anybody is in love with this syntax, but that's the CSS that is supported today.
There are fancier solutions involving additional custom elements to manage dynamic, shared style-sheets, but it's a larger topic. Polymer will offer some kind of solution around these lines before long.