16

Using stuff like document.getElementByTagName, you can practically create your own elements.

<arial>Hello</arial>

And then in JS..

var a = document.getElementsByTagName("arial");

for(i = 0; i < a.length; ++i)
     a[i].style.fontFamily = "Arial"

And we have a custom element, easy peasy.

My question comes down to, is this bad practice? Is there some drawback I'm not noticing?

bobbybee
  • 1,758
  • 1
  • 16
  • 27
  • you don't create any new "own" element here, you just apply some css to a block node element. – Sebas Aug 11 '13 at 22:52
  • Sebas: I know, but this would be for more advanced cases where there is real functional differences – bobbybee Aug 11 '13 at 22:54
  • Have a look at this question: http://stackoverflow.com/q/2802687/1602864 – nirazul Aug 11 '13 at 22:54
  • 6
    I once read a blog, wherein some old code was discussed. A (then) custom attribute was added to a bunch of elements. The attribute's name was language..... FastFwd to HTML5 and the whole page (and site) breaks - spectacularly. Unfortunately it was said, the attribute `language` was now a part of the standard and caused to browser to exhibit new and unwanted behaviour. Remembering this, I suggest that you're much better off creating elements that already exist (i.e are defined in the html5 spec) before then giving them IDs or CLASSs that are unique and/or offer the ability to target with css. – enhzflep Aug 11 '13 at 22:55

5 Answers5

26

The W3C says you should not. It is bad practice.

Authors must not use elements, attributes, or attribute values that are not permitted by this specification or other applicable specifications, as doing so makes it significantly harder for the language to be extended in the future.

Furthermore, HTML5 is not XML. You should only use the elements outlined in the official spec.

Michael Irigoyen
  • 22,513
  • 17
  • 89
  • 131
  • 1
    I understand why the W3C would be against it, but I'm thinking more practical problems (ya know, search engines or browsers not rendering or something like that) – bobbybee Aug 11 '13 at 22:59
  • You always take the risk of negatively affecting how search engines index your site if you begin using invalid code. In addition, there is a ton of overhead to create new elements, especially if you need to your site to work across browsers, old and new. Lastly, if an element you create later gets added into the spec, or a browser starts looking for an element with the same name you came up with, it can have negative consequences. In short, don't do it. Add descriptive `id`s and `class`es. – Michael Irigoyen Aug 11 '13 at 23:03
  • 7
    @bobbybee to give you a practical example, [look at all these people crying and having a huge sense of entitlement](https://code.google.com/p/v8/issues/detail?id=164) when they relied on something they shouldn't have but what appeared to work just fine for a decade. Maybe they didn't know about the risks but now you do. – Esailija Aug 11 '13 at 23:09
  • @Esailija so basically... don't? – bobbybee Aug 11 '13 at 23:17
  • @bobbybee the usefulness of custom tag is very limited... so yeah don't. Just use `data-` attributes like `
    – Esailija Aug 11 '13 at 23:19
  • @Esailija Is it illegal to do `
    `?
    – bobbybee Aug 11 '13 at 23:21
  • @bobbybee custom attribute has same problems as custom tag names. Html5 introduced many custom attributes that have special meaning... like `required` or `autofocus` . – Esailija Aug 11 '13 at 23:22
  • 1
    @bobbybee Read my answer again concerning attributes. "Authors must not use elements, attributes, or attribute values that are not permitted by this specification..." – Michael Irigoyen Aug 12 '13 at 03:46
  • 1
    @MichaelIrigoyen Although note that HTML5 *does* allow for custom attributes that are prefixed with 'data-' - see http://html5doctor.com/html5-custom-data-attributes/ (and this is used in a number of libraries, such as Lightbox 2 which is where I first saw it) – fluffy Aug 12 '13 at 06:10
  • @fluffy Yep, `data-` attributes are permitted by the specification. Good to clarify, though. – Michael Irigoyen Aug 12 '13 at 13:08
  • @MichaelIrigoyen That being the case, why are Google allowed to get away with this? Angular/Angular2 apps are littered with non-standard tags and attributes? – Matthew Layton Jan 25 '17 at 15:29
6

The major drawback with this is it's not semantically valid. However, the browser will parse it pretty fine as a block element, until you add more style to it.

Instead of making your own tags, use class, and perhaps data attributes to add appropriate attributes to your DOM.

Bartek
  • 15,269
  • 2
  • 58
  • 65
  • 2
    `data-` attributes can handle a lot of different use cases. – David Tansey Aug 11 '13 at 22:52
  • What precisely is the problem with block elements (I'm rather bad at HTML opposed to JS)? – bobbybee Aug 11 '13 at 22:57
  • There is no problem :) I'm just saying the browser will interpret any element that it doesn't know what it is as a block element, instead of say, an inline one. – Bartek Aug 11 '13 at 23:00
  • Right, there is no technical problem with using custom elements (for right now anway, see the comment about a `language` attr for a parable). But don't say that out loud, because there is a *practical* reason to avoid them: it's not worth arguing about, and the only people who care are the people who don't like them. – AdamKG Aug 11 '13 at 23:03
  • You are partially incorrect, @Bartek. Not all browsers render unknown elements as block. IE, for example, [needs to have them specified as so](http://modernizr.com/docs/#html5inie). Again showing how much of a can of worms you're opening by trying to create your own elements. – Michael Irigoyen Aug 11 '13 at 23:05
  • @MichaelIrigoyen Ah, of course IE likes to twist things around :) – Bartek Aug 11 '13 at 23:46
  • I don't think needing to define "display: block" in the CSS is exactly a can of worms. However if there are other problems, or browser support table I would like to see it. Even when writing just HTML (no JS) it would be benifical to be able to define elements (with dashes). – Ciantic Dec 31 '15 at 07:41
3

Generally, you want to use the standard html elements and use their ID or class to locate them. It will produce much cleaner and useable code.

kery
  • 381
  • 2
  • 12
2

I wouldn't say it's bad practice, but it's really overkill in almost any kind of situation and it will make your HTML markup invalid according to the W3 Validator. What you could do instead is give your element a class and then refer to it in JavaScript by using getElementByClass:

// Grabs the first element with said class
var foo = document.getElementsByClassName()[0];
federico-t
  • 12,014
  • 19
  • 67
  • 111
0

Forward Compatibility

As mentioned in the comments, creating elements like this is unsafe. For example, pretend the input element didn't exist, but was created later.

<input>Some Content</input>

Browsers rewrite this to (XHTML for clarity):

<input />Some Content

SEO and Accessibility

HTML5 pages provide elements that describe the content. This helps search engines to understand your page. If they don't understand your page, it could lower your ranking.

If you insist on using these tags, and use them for more than a block of text, you should give them roles and aria-tags. This aids search-engines and people requiring screen-readers or other accessibility services.

Styleability

Some browsers won't let CSS styles take effect until you create an element programmatically. It's the same technique used by the html5shiv to get old browsers to support the new HTML5 elements.

document.createElement("arial"); // don't need to do anything with it

Browser Alternative: data-*

demo

You can use data-something attributes to tag elements for replacement. For example:

<span data-large>Large Text</span>

Then, you can use a rewriter to replace these with different HTML. This example uses jQuery and an extremely simple templating language.

rewrites = {
    large: '<span style="font-size: 2em">{}</span>'
};

function rewrite(r) {
    for (rule in r) {
        // build a selector in the form of [data-something]
        var selector = "[data-{}]".replace("{}", rule)
        $(selector).each(function (i, el) {

            // get our inner html and inject it into our template
            var inner = $(this).html();
            var templated = r[rule].replace("{}", inner);

            // replace the element with our new HTML
            $(this).replaceWith(templated);            

        });
    }
}

rewrite(rewrites);

Server Side / Build

You can write your code using any tags you like, but transform it on the server before it reaches your browser. Here's a demo written in jQuery (client-side) but compatible with Cheerio (nodejs).

rewrites = {
    large: '<span style="font-size: 2em">{}</span>'
};

function rewrite($, r) {
    for (rule in r) {
        $(rule).each(function (i, el) {
            var inner = $(this).html();
            var templated = r[rule].replace("{}", inner);
            $(this).replaceWith(templated);            
        });
    }
}

rewrite($, rules)

This can either be worked into a build-script, or as a very simple server-side template. This way, browsers and search engines never see our made up elements. I recommend this solution, if you need these virtual elements.

Brigand
  • 84,529
  • 20
  • 165
  • 173
  • Using custom tags in AngularJS is not any different, if in future new semantics are attached to currently meaningless custom element, it can have unknown side-effects regardless of AngularJS. – Esailija Aug 11 '13 at 23:17
  • Not true. You can replace the entire element, so unless new browsers add an element that rejects the DOM api, this won't be a problem. I'll add a better alternative. – Brigand Aug 11 '13 at 23:19
  • 4
    But the element is still in the html and parsed before any angular takes effect. Let's say your element name is `` or `` and in future it means any elements under it become shadow dom or whatever. Then angular code for that would break. Just an example. – Esailija Aug 11 '13 at 23:20
  • Good point. I added a server side alternative. If you're worried about changes in HTML, just don't upgrade your parser without making sure it doesn't break anything. – Brigand Aug 12 '13 at 00:02
  • @Esailija, I updated my answer. Do you have any further input on it? – Brigand Aug 12 '13 at 00:45
  • Yes server side template processing avoids any problem with custom elements (if they are not in the output) but I don't think that is what OP meant. :p – Esailija Aug 12 '13 at 08:54