Related
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>
I have a problem with my web. When I set css for #responzivniMenu (display: none;) It's still displaying and might not change. I don't know where does the problem come from.
[SOLVED] It was problem with hosting! Check my answer post if you are interested what exactly was the problem.
My HTML:
<div id="responzivniMenu">
<div id="skautLogoResponzivni"></div>
<div class="responzivDrop">
<button onclick="responziv()" class="responzivBtn"></button>
<div id="responzivni" class="responzivni-content">
Domů
Historie
Aktuality
Vedoucí
Kontakt
Oddíly
</div>
</div>
<script>
function responziv() {
document.getElementById("responzivni").classList.toggle("resshow");
}
window.onclick = function(event) {
if (!event.target.matches('.responzivBtn')) {
var dropdowns = document.getElementsByClassName("responzivni-content");
var i;
for (i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('resshow')) {
openDropdown.classList.remove('resshow');
}
}
}
}
</script>
</div>
And CSS:
#responzivniMenu {
display: none;
}
your css style is overrided by another css rule,try adding !important after display:none.
#responzivniMenu {
display: none!important;
}
check your css file. it may contain a specific css for your #responzivniMenu that override yours
In your html i didn't saw where you are linking your css to the page.
If your css it's on the same page than your html but not in a separated page, so you must use "style" tag an your code will be
<style>
#responzivniMenu
{
display:none !important;
}
</style>
Sorry guys for this post, my hosting just has a long delay between uploading the file and changing it on the server for some reason. It's about one hour. Thanks for all your replies and I apologize for wasting your time!
Can anybody advise me on this? WebKit browsers keeps on putting a gray 1px border around disabled images. The reason I need this removed is for email optimization for when email clients have images disabled. Works fine in Firefox, but WebKit browsers keep showing the border.
I have tried border:none !important everywhere including inline, but Chrome/Safari are being stubborn.
Edit: Here is sample html with inline css
<img style="outline:none;text-decoration:none;display:block;border:none;-webkit-border:0;" border="0" src="images/rm_bnk.gif" width="10" height="10" alt="test" />
Amit's answer is just great, but a small advice:
use visibility: hidden; instead of display: none;
img:not([src]) {
visibility: hidden;
}
so you could save img block size and positioning of other elements. its usefull in most cases, i use it on my sites with images lazyload and show just blank block before the image loads.
If img src is not present or broken then use below css code
img:not([src]){ display:none; }
this css hide image till img src is not loaded completely.
There is no way to remove it but I wrapped the image in an element that has overflow hidden property in its styles.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Hide Broken Image border</title>
<style>
body{
background-color:azure;
}
.image-container{
width:100px;
height:100px;
overflow:hidden;
display:block;
background-color:orange; /*not necessary, just to show the image box, can be added to img*/
}
.image-container img{
margin:-1px;
}
</style>
</head>
<body>
<span class="image-container">
<img src="path-to-image" alt="I'm Broken :(" width="102" height="102">
</span>
</body>
</html>
Take a look at this bin
http://jsbin.com/OpAyAZa/1/edit
Browsers don't seem to really give you a way to remove that border. Your simplest solution is to change your img to a div and apply the image as a background.
That way, if there's no src, you won't get the broken image icon and border.
Update: Microsoft Outlook makes things difficult, and the cure is almost worse than the disease: vector markup language, shape elements, imagedata elements, etc. If you google around you'll see how to use them http://blog.oxagile.com/2010/04/23/background-images-for-outlook-2007-and-outlook-2010-beta/
Outlook users might just have to go without the image so that you can call it a day.
Try using some JavaScript to remove the broken image. Thats the only way
var images = document.getElementsByTagName("img");
for (i = 0; i < images.length; i++) {
var self = images[i];
self.onerror = function () {
self.parentNode.removeChild(self);
}
}
Because rendering of broken image varies from browser to browser and it could not be altered.
P.S: onerror will fire when the image is not loaded
You can try this code to remove borders around broken images in webkit.
var images = document.getElementsByTagName("img");
for (i = 0; i < images.length; i++) {
var self = images[i];
self.onerror = function () {
self.parentNode.removeChild(self);
}
}
I am using chrome version 18.0.1025.162 m
I have html file with iframe within it.
i cant change the containing page or its css (main.htm)
i can only change the iframe (show.htm) and its css.
The problem is that when i scroll down and then scroll back up then the adminbar div get replicated several time.
I am attaching 2 screenshots the first one is the screen before scrolling and i also add the code so that the bug can be reproduced.
I think it may be a bug in chrome, i am not sure.
I would like to know if it is a a bug and more importantly if there is a work around by only changing the iframe and that it does not include removing the background color from the iframe.
(removing the background color from the iframe solve the issue but i need the background color)
so this is how it looks:
before scrolling:
after scrolling (admin bar get replicated on screen)
now code to reproduce the bug in chrome
first file - main.htm (i cannot change this code)
<!-- main.htm -->
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
#adminbar
{
background-color: #464646;
height: 28px;
position: fixed;
width: 100%;
top: 0;
}
#body-content
{
float: left;
width: 100%;
}
</style>
</head>
<body >
<div id="body-content">
<iframe src="show.htm" width="100%" height="943"></iframe>
<div id="adminbar" class="" role="navigation">
</div>
</div>
</body>
</html>
and the show.htm
<!-- show.htm -->
<!DOCTYPE html>
<head>
<style type="text/css">
body
{
background: #e0e0e0;
}
</style>
</head>
<body>
<br/>
<p style='margin-bottom:500px;'>bazinga</p>
<p style='margin-bottom:500px;'>bazinga</p>
<p style='margin-bottom:500px;'>bazinga</p>
</body>
</html>
i think i found a workaround.
i created a file background.png which has one pixel with the color i want (#e0e0e0).
i then replace this:
body
{
background: #e0e0e0;
}
with this:
body
{
background: #e0e0e0 url(background.png) repeat-x;
background-attachment: fixed;
}
Add -webkit-transform: translate3d(0,0,0); to your body-content CSS
CSS
#body-content {
float: left;
width: 100%;
-webkit-transform: translate3d(0,0,0);
}
This seems to force Chrome to use your GPU and smooth out the rendering issue.
UPDATE: Since you can't change main.htm, what about changing the background color of show.htm to a background image of the same color? I tested this and it worked. Is that a possibility?
I recreated your setup and then added a script to the body of show.htm. As a quick measure I added a name="if1" to the <iframe /> in main.htm, but you could always find a handle on the element without using an explicitly assigned name.
It seems to solve the issue for the dummy setup that you provided, if and only if main.htm is scrolled all the way to the top. Think it's weird, join the club! See if this works for the real thing... Either way, it may just be a nudge in the right direction! :)
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body
{
background: #e0e0e0;
}
</style>
</head>
<body>
<br/>
<p style="margin-bottom:500px;">bazinga</p>
<p style="margin-bottom:500px;">bazinga</p>
<p style="margin-bottom:500px;">bazinga</p>
<script type="text/javascript">
window.onscroll = function(){
console.log("It's 'Doctor' Sheldon Cooper!");
//parent.document.if1.document.body.style.webkitTransform = 'scale(1)';
var _parentScale = parent.document.body.style.webkitTransform;
parent.document.body.style.webkitTransform = _parentScale;
}
</script>
</body>
</html>
I also tried to experiment with the following until it became bed-time!
<script type="text/javascript">
window.onscroll = function(){
console.log("It's 'Doctor' Sheldon Cooper!");
//parent.document.if1.document.body.style.webkitTransform = 'scale(1)';
var _me = document.body;
_me.style.webkitTransform = _me.style.webkitTransform;
//_me.style.display='none';
_me.offsetHeight
//_me.style.display='block';
var _parent = parent.document.body;
_parent.style.webkitTransform = _parent.style.webkitTransform;
_parent.style.display=_parent.style.display;
_parent.offsetHeight
//_parent.style.display='block';
}
parent.window.onscroll = function(){
console.log("But. You're in my spot!");
//parent.document.if1.document.body.style.webkitTransform = 'scale(1)';
var _me = document.body;
_me.style.webkitTransform = _me.style.webkitTransform;
//_me.style.display='none';
_me.offsetHeight
//_me.style.display='block';
var _child = parent.document.if1.document.body;
_child.style.webkitTransform = _child.style.webkitTransform;
_child.style.display=_child.style.display;
_child.offsetHeight
//_child.style.display='block';
}
</script>
I also attempted to apply j08691's answer, using the following script, but it gave slightly unexpected results. I caused the absolute positioned top bar, to not be fixed, among other things!
window.onload = function(){
console.log("It's 'Doctor' Sheldon Cooper!");
var test = parent.document.getElementById("body-content");
test.style.webkitTransform = "translate3d(0,0,0)";
}
One may already exist, but if not, could you file this as a bug report on the relevent projects?
Improving / simplifying yossi's answer:
body
{
background:url('bg.png');
}
no need to declare bg-color or repeat-x, just needs a background image.
Tested on Chrome 18.0.1025.168, Mac OS X 10.6.8.
Remove the float: left; from your #body-content css and it will work just fine.
This looks to be a rendering bug in chrome. If you scroll back up really slowly, you'll notice that you get a solid colour from your admin bar as the colour of your iframe.
Incidentally chrome on OSX renders exactly the same.
#adminbar {
background-color: #464646;
height: 28px;
position: fixed;
width: 100%;
top: 0;
right:0px
}
#body-content {
float: none;
width: 100%;
}
It would help to get a live-demo/version of your actual website to do more thorough testing and sort the bug out.
In any case, I was able to reproduce the bug and then fix it (kind of):
Here's the 'show' css:
body
{
background: #e0e0e0;
height:100%;
width:100%;
z-index:9999;
position:fixed;
}
and Here's the link to my test page:
sotkra.com/t_main.html
last but not least, yes it is a bug and it caused by the flickering of the scrolling of the iframe content against the actual 'base' document. I've seen similar issues before but there was equally no documentation about it. They're just rendering bugs, usually caused by less than specific css or very very odd cases where it's nobody's fault save the browser's.
Cheers
G
Using a gradient as your background image also works. This is preferable for me, because I don't have to create an image file and it doesn't generate an extra request on the client side.
body {
background: #FFF -webkit-linear-gradient(top, #FFF, #FFF) repeat-x;
background-attachment: fixed;
}
I need to use a textarea to show some text. The problem is that if I place 4-5 rows of text a scrollbar will appear. How can I use CSS/HTML so that the textarea will be as large as it's content (no scrollbar).
the textarea doesn't need to change it's size dynamicaly, I use it only to show a text (I could also use a disabled textarea)
I want the textarea to stretch only verticaly.
If you want to know:
I use the textarea to show some text from a database, so when the textarea (with the text in it) is created, it should show the whole text at once with no scrollbars.
<!DOCTYPE html>
<html>
<head>
<title>autoresizing textarea</title>
<style type="text/css">
textarea {
border: 0 none white;
overflow-y: auto;
padding: 0;
outline: none;
background-color: #D0D0D0;
resize: none;
}
</style>
<script type="text/javascript">
var observe;
if (window.attachEvent) {
observe = function (element, event, handler) {
element.attachEvent('on'+event, handler);
};
}
else {
observe = function (element, event, handler) {
element.addEventListener(event, handler, false);
};
}
function init (maxH) {
var text = document.getElementById('text');
var maxHeight=maxH;
var oldHeight= text.scrollHeight;
var newHeight;
function resize () {
text.style.height = 'auto';
newHeight= text.scrollHeight;
if(newHeight>oldHeight && newHeight>maxHeight )
{
text.style.height=oldHeight+'px';
}
else{
text.style.height = newHeight+'px';
oldHeight= text.scrollHeight;
}
}
/* 0-timeout to get the already changed text */
function delayedResize () {
window.setTimeout(resize, 0);
}
observe(text, 'change', resize);
observe(text, 'cut', delayedResize);
observe(text, 'paste', delayedResize);
observe(text, 'drop', delayedResize);
observe(text, 'keydown', delayedResize);
text.focus();
text.select();
resize();
}
</script>
</head>
<body onload="init(200);">
<textarea rows="1" style="height:1em;" id="text"></textarea>
</body>
</html>
http://jsfiddle.net/TDAcr/
I´m afraid you´ll have to resort to javascript to set the height of your textarea. You can use the scrollHeight property to determine the total height.
Alternatively you could just use a div and style the div to look like a textarea. The div will grow automatically and as it´s a disabled textarea anyway, you don´t really need it to be a textarea.
Alright, I just found this and it works very nicely:
<html>
<head>
<script>
function textAreaAdjust(o) {
o.style.height = "1px";
o.style.height = (25+o.scrollHeight)+"px";
}
</script>
</head>
<body>
<textarea onkeyup="textAreaAdjust(this)" style="overflow:hidden"></textarea>
</body>
</html>
Now, I shouldn't assume that you know Javascript (but you might).
Just run
textAreaAdjust(document.getElementById("id of your text area"))
Something like that should work. I'm not the best with Javascript (not even close, I just started using it the other day)
That seems to do something similar to what you want. The first code example is for a textarea that dynamically changes based on what is in it (while typing). It will take a couple of changes to get it how you want.
You could use the CSS height: and width: attributes, e. g. something like
<textarea style="width:400px;height:300px">...</textarea>, just use the sizes you want to.
In addition, if you want to suppress the scrollbar, use overflow:hidden.
you can use div like textarea. It is possible like this:
<div contenteditable="true" style="width:250px; border:1px solid #777" ></div
Find the height of the font you will most likely be displaying it in. I'm not sure about CSS/HTML but you could use Javascript/PHP/ASP.net to use map to determine how big the text will be based on the number of characters. If you do it in a monospaced font, this will be even easier. Why use a text area when you could just use a label which will do the same thing all by itself?
If you don't mind using JavaScript you can use approach from one of following articles:
http://james.padolsey.com/javascript/jquery-plugin-autoresize/
http://scvinodkumar.wordpress.com/2009/05/28/auto-grow-textarea-doing-it-the-easy-way-in-javascript/
But from your questing I assume you want pure CSS solution.
Then you can just mimic appereance of textarea using simple div and following css (if you just want to display text):
div {
cursor: text;
background: lightGray;
border: 1px solid gray;
font-family: monospace;
padding: 2px 0px 0px 2px;
}
I assume name attribute is not used. You can use this alternative (HTML5):
http://jsfiddle.net/JeaffreyGilbert/T3eke/
Using the resize property works these days:
resize: none;