I have not worked extensively on Client Side/Front End of the Application and I am trying to read about HTML, CSS and DOM but somehow am not able to figure out difference between them and so would really appreciate if someone can:
Explain me in simple English how does HTML, CSS and DOM work ?
How do they relate to each other from Client Side Technology point of view ?
Update
I have gone through wikipedia articles but not able to clearly understand working of DOM.
Thanks.
What is the DOM?
Let's say you open a web browser (e.g. Chrome) and load a web page in it (e.g. stackoverflow.com). Now, inside the browser, there is an window object. This object represents the browser window.
This window object has dozens of properties (members), the most important of them being the document object. The document object represents the web page that is currently loaded into the browser window.
This document object is the root of the DOM tree:
(source: w3schools.com)
Each box in the above picture is a node inside the DOM tree. A node is an object that is "connected" to other objects from the DOM tree.
The JavaScript programs that are bound to a web page have complete access to every node of the DOM tree. They can delete nodes, add new nodes, or just manipulate the properties of a node.
To sum up, inside the browser there exist hundreds of objects. All these objects are connected (somehow), and this huge structure of inter-connected objects is the DOM.
HTML is what is on your website (headings, lists, tables)
CSS is what those things look like (borders, colours, font sizes)
DOM is how you access those things through javascript (getting nodes, adding new elements, changing their style)
Here is an example of the 3 working together (doesn't seem to work in ie)
http://jsfiddle.net/gj9zT/
HTML describes the structure of a document. The browser parses HTML and constructs an internal representation of the elements of the document from it, like:
document
|
|-body
|
|-div
| |
| |-p
| |
| |-"some text"
|-div
|
|-...
This internal representation is the DOM, the Document Object Model. This is the basis for creating the actual visual representation of the website.
CSS is used to define how this visual representation looks exactly.
Parts of the DOM are also exposed through an API, so you can manipulate the DOM (i.e. the document) using a programming language like Javascript.
Have a look at
Confused by relation between DOM and HTML (APIs)
Difference between html and dom
Its a long explaination but i will try to explain in brief
CSS: These are used to apply property's to html elements. If you want to apply a common color to various html elements we can do it in css and apply that class to html element. We can avoid repeatation of code with css.
We can achieve many other things with css. Read in google
HTML: HTML is nothing but various kind of tags we use to display the elements like tables , divs , p , ul , li etc
DOM: DOM is nothing but the relation between the html elements , we use javascript normally to manipulate the DOM like changing height , moving from one place to another...
There will be lot of links in google , you can better explanations.
HTML (HyperText Markup Language) is the markup we use to describe the structure of our page. It defines the different constructs like <ol></ol> Ordered List or <table> Tables etc...
HTML is the code we start with, it's human readable (well it's supposed to be anyway :p) and easily compressable & transferable.
DOM (Document Object Model) is the framework your computer uses to organize the page it renders from HTML. When your computer breaks down your HTML Document it organizes it into an Object Model which it can more easily work with (and so can you, in javascript/css/etc...).
CSS (Cascading Style Sheets) describe how you want items in your documents to look. They're named cascading style sheets because they "cascade" down to the next one to fill in the holes or override styling. CSS describes the visual qualities of the objects in the DOM.
HTML is effectively the markup of your DOM (Document Object Model). The root of the document is <html>, which contains many levels of <div>s, <p>aragraphs, <h1>eaders and so on.
The DOM is the tree (graphical structure) of your html markup. It will have a 'root', which has many 'children', the children will have 'siblings' and 'parents', 'descendants' and 'ancestors'. The root doesn't have a parent, and is an ancestor of all the descendant nodes. for instance, your typical html document will be structured like this:
<!DOCTYPE html>
<html>
<head>
<title>Banner Example</title>
<style type="text/css">
#header {
background-image: url('branding_logo.jpg');
}
h1 a {
display: block;
height: 120px;
width: 500px;
text-indent: -9999; /* to hide the text that would show */
/* over the banner */
border: 1px solid black;
}
</style>
</head>
<body>
<div id='header'>
<h1>This is a header link.</h1>
<p>Here is some text.</p><p>Here is some more text.</p>
</div>
<div id="content">
<p>here is a bunch of content.</p>
</div>
</body>
</html>
In this case, html is the root node, which has two children: head and body. Head and body are siblings. You can use the DOM model with selectors in order to select which objects (contained in a node) will be affected by code such as CSS.
CSS will take selectors and style them as you specify in its attribute block. You could select all elements <p>, using
p { color: red; }
Or you could select only 'p' where it's a descendant of a div whose id is content:
div#content { color: black; }
CSS will typically style a tag using the most specific DOM description that can be applied to it. So, in my above html example, the first css style will apply to all p, and then the second, more specific styling will be applied to only that one p in the content div.
Essentially, what happens is your browser will parse your HTML code into sections that allow them to be selected individually. That parsed structure is your DOM. CSS uses the DOM to apply styles. jQuery does the same, allowing you to select a specific node from the DOM and apply styles or actions to that node dynamically on the client side.
Related
After carefully reading all related articles and posts on many sites, there is still one remaining question: Can i have a single, exchangeable CSS for a web app built with web components widhtout having to deal with all the weird stuff suggested by W3C?
I know about ::part( something ) and exportparts="something" to access nested components, but that does not go down the tree, so I have to add a part attribute to almost every element, which totally bloats my HTML.
Having an #import rule in each component is also not a great option, because it would be one more HTTP request per stylesheet. Also, once loaded in a template, the importet css can not be exchanged easily.
W3C really makes our lives harder by removing /deep/ and ::shadow. I know, performance concerns, blah, blah, but at least that worked like a charm.
Possible solutions I find impractical:
How to style slotted parts from the parent downwards
::slotted CSS selector for nested children in shadowDOM slot
How to access elements inner two shadow dom
Example HTML where all nested elements would be styleable with global CSS:
<body>
<o-app>
#shadowDOM
<o-header exportparts="username:o-textinput__username,action-ok:o-action__action-ok,o-action__label" part="o-header">
#shadowDOM
<o-texinput part="username">
<o-action exportparts="label:o-action__label" part="action-ok">
#shadowDOM
<div part="label">
Then I can finally style the label div by selecting it with:
::part( o-action__label ) {}
Now tell me that having to specify every single part of all descendant elements in the parent elements is not a total mess!
Playaround on Codepen: https://codepen.io/5180/pen/jOyQNYq?editors=1111
Now in 2021 I would rather use light DOM only instead of forcing the shadow DOM to behave like its counterpart, because there is currently no easy method of piercing through the artificial boundary. It was in the spec – ::shadow and /deep/ – but got removed, so deal with it. ::theme() is not ready yet, The ::part() selector is useless for deep styling as I pointed out in my example.
Just use the light DOM (innerHTML) of your custom element to avoid deep styling/theming issues.
I want to build an external GUI that operates on a generic HTML piece that comes with associated CSS. In order to enable some functionalities of the GUI, I would need to create some "meta" HTML elements to contain parts of content and associate them with data.
Example:
<div id="root">
<foo:meta data-source="document:1111" data-xref="...">
sometext
<p class="quote">...</p>
</foo:meta>
<p class="other">...</p>
</div>
This HTML is auto-generated starting from already existing HTML that has associated CSS:
<div id="root">
sometext
<p class="quote">...</p>
<p class="other">...</p>
</div>
#root>p {
color:green;
}
#root>p+p {
color:red;
}
The problem is, when adding the <foo:meta> element, this breaks CSS child and sibling selectors. I am looking for a way for the CSS selectors to keep working when encapsulating content in this way. We have tried foo\:meta{display:contents} style, but, although it works in terms of hiding the meta element from the box renderer, it doesn't hide it from the selector matcher. We do not produce the HTML/CSS to be processed, so writing them in a certain way before processing is not an option. They come as they are, generic HTML documents with associated CSS.
Is there a way to achieve what we are looking for using HTML/CSS?
To restate, we are looking for a way to dynamically encapsulate parts of content in non-visual elements without breaking child and sibling CSS selectors. The elements should only be available to DOM traversal such as document.getElementsByTagName('foo:meta')
If I understood your problem correctly.I would suggest using the space between the grandparent and the child instead of a '>'. Also your selector is an id and not a class.
The selector you have put in selects the next level child that is the children. But adding the space in between enables you to select grandchildren too!
so you have do is this
#root .quote {
color:green;
}
Let me know if this helped.
A working css is here
So, after much fiddling and research, we came to the conclusion that this can't be done, even with ShadowDom, as even that would require massive CSS rewrites that might not preserve semantics.
However, for anyone stumbling upon this question, we came to the same end by employing the following (I'll be short, pointers only):
using two comments to mark where the tag would start/end, instead of an XML tag (eg. <!--<foo:bar data-source="1111">-->...content...<!--</foo:bar>-->)
these pointers work more or less like the markup equivalent of a DOM Range and they can work together with it.
this approach has the interesting advantage (as opposed to a single node) that it can start and end in different nodes, so it can span subtrees.
But this also breaks the XML structure when you try to recompose it. Also it's quite easy by manipulation to end up with the range end moving before the range start, multiple ranges overlapping etc.
In order to recompose it (to send to a next XML processor or noSQL XML database for cross-referencing), we need to make sure we avoid the XML-breaking manipulations described above; then, one only needs to convert encapsulated tags to regular tags by using string manipulation on the document (X)HTML (innerHtml, outerHtml, XMLSerializer) to get a clean XML which can be mined and cross-referenced for content.
We used the TreeWalker API for document scanning of comments, you might need it, although scanning the document for comments this way can be slow (works for us though). If you are bolder you can try using xPath, ie. document.evaluate('//comment()',document), seems to work but we don't trust all browsers comply.
I should start off by saying that I don't really have an issue that I'm trying to work through. I just had an interesting thought about how Shadow Dom and the CSS3 :target selector might / should / currently do work together.
I know that HTML specification says that there should only ever be one element with a particular ID value in a valid HTML document. But when we start using webcomponents with shadow dom we could very easily find ourselves using multiple elements with the same ID. This is especially true when we use the same component multiple times in the same page. So the question that I have is this: what should happen to an element inside a shadow dom region that has an ID value which matches the current hash and which is styled with a :target rule?
For example, if I wrote a webcomponent (my-element) that contained
<style>
#debug {display:none}
#debug:target { display:block; background-color:yellow; border 2px solid red; }
</style>
<div id="debug">some debug data</div>
What should happen to all the instance of my-element that I put on a page and navigated to #debug on? Should the debug element in each component show? Should none of them show? Should only the first element's debug div show (the same one I'd expect the browser to try and navigate to)?
My opinion is that if the page does not have an element with an ID=debug value that no scrolling navigation should appear on the page. As shadow dom is isolated from the rest of the page's styles the browser shouldn't try to navigate to such an element nested in shadow dom. Each my-element instance should be able to see the current page's URL though and should apply any matching :target rules, such that each my-elements' debug div should be visible.
If this were the case it would make for some interesting possibilities for sharing page state across all components, such as the debug example above. However, I doubt that is how Chrome is currently implementing things. And I'm pretty sure this Shadow Dom polyfill isn't going to handle things correctly as it basically shoehorns everything into the page's Dom tree and that would break the html specification.
Just curious if anyone has an answer for how this should work and how it works today...
(edited from my pc to add formatting... hard to do from my phone)
I think you can see the shadow DOM like a nested document. CSS can't address elements inside the shadow DOM from the outside (previously existing shadow piercing CSS selectors were deprecated).
This also encapsulates ids and therefore multiple components that contain elements with an id won't cause collisions or duplicates.
If you have the CSS with the :target selector inside a components style, it should be able to address the element with the matching id, otherwise it shouldn't.
So the question that I have is this: what should happen to an element
inside a shadow dom region that has an ID value which matches the
current hash and which is styled with a :target rule?
Adding to Günter Zöchbauer above answer an alternative is to use the Custom Element object when the style is encapsulated, if the style is global it will work just fine. Use the define method to create a custom component as shown in the the docs. This will not encapsulate your elements so be aware that your styles can be shared across files.
So instead of doing this:
const shadow = this.attachShadow({ mode: "open" });
shadow.appendChild(pTag)
Use this:
this.appendChild(pTag);
both previous examples suppose you're in a HTMLElement class or a class that inherits it.
Can I use this (custom elements, custom attributes) on (for examples) IE 9 with this CSS? Is this valid? What are the negatives?
I want to have more readable code... without divs.
HTML
<row center>
<column number="6">A</column>
</row>
CSS / LESS
row {
background: #444;
display: flex;
&[center] {
justify-content: center;
}
column {
background: #222;
color: #fff;
&[number="6"] {
padding: 1rem;
width: 50%;
}
}
}
The case against custom elements has been made by other answers. As an alternative to this idea, HTML 5 has a number of new elements. These include <article>, <aside>, <figure>, <header>, <nav>, and <section>. Using these elements should make your page layout semantically meaningful, save you from puzzling over a sea of <div> and <span> elements, and be understood by modern browsers.
Making up your own markup language:
May conflict with additional features added to HTML in the future (at least if you tell the browser it is HTML with a Content-Type: text/html HTTP header).
Won't be properly understood by user agents which you can't completely override with CSS (such as screen readers, text browsers and search engines).
Won't be understood by other developers who may have to maintain your code in the future.
Can't use an HTML validator for a cheap, basic QA pass
The W3C is developing a standard call Custom Elements, which allows authors to define their own elements. You can read about it here:
Custom Elements, defining new elements in HTML
Custom Elements allow web developers to define new types of HTML
elements. The spec is one of several new API primitives landing under
the Web Components umbrella, but it's quite possibly the most
important. Web Components don't exist without the features unlocked by
custom elements:
Define new HTML/DOM elements
Create elements that extend from other elements
Logically bundle together custom functionality into a single tag
Extend the API of existing DOM elements
Introduction to Custom Elements
Custom Elements enable developers to create their own custom HTML
tags, let them use those tags in their sites and apps, and enable
easier component reuse.
W3C Custom Elements
Provide a way for Web developers to build their own, fully-featured
DOM elements. Though it was long possible to create DOM elements with
any tag names in HTML, these elements weren't very functional. By
giving Web developers the means to both inform the parser on how to
properly construct an element and to react to lifecycle changes of an
element, the specification eliminates the need for
DOM-as-a-render-view scaffolding that has to exist today in most web
frameworks or libraries.
However, if your goal for today is to write more readable code, then consider sticking with standard HTML elements (or just div and span elements) and using class and id values for descriptions. You can be as descriptive as you like with classes and ids. See my answers here for guidance:
Default settings of unrecognized HTML elements
Is there a standard method for naming classes?
HTML5 ID Attribute Values
considering I have a single css file for my entire website (and that doing so is an usual technique), I was wondering if there is a way to select website-wide attributes like body (or any other attribute in fact) according to the current page using only css.
Something like
body:in('index.html') {
some properties;
}
body:in('contact.html') {
other properties;
}
Again, css only. I know the simple solutions using things like php, js, jquery...
Selectors have no information about the document beyond what is presented in the DOM tree, and the DOM does not expose information about the page according to its file name, URL, or any other such properties.
Historically there was a #document at-rule for querying the current URL, but it was removed from the Conditional Rules Level 3 module. The most likely reason for this is the lack of cross-vendor implementations, as the only known implementation exists in Gecko, as #-moz-document. It's so bad, that the only uses for it that you'll spot in the wild are not to apply CSS based on a certain page, but solely as a CSS hack for Firefox.
As you've stated, the simplest workaround for this is to have each page apply a unique class to the html or body element and select according to that class, whether via hardcoding, or dynamically.
you could add and id atribute to the body tag and style things inside it using:
body#contact div{
background:#376;
color:#857;
/*etc*/
}
more information about selectors in http://www.w3.org/TR/css3-selectors/