admin管理员组

文章数量:1128405

Recently I have been reading more and more about people using custom attributes in their HTML tags, mainly for the purpose of embedding some extra bits of data for use in javascript code.

I was hoping to gather some feedback on whether or not using custom attributes is a good practice, and also what some alternatives are.

It seems like it can really simplify both server side and client side code, but it also isn't W3C compliant.

Should we be making use of custom HTML attributes in our web apps? Why or why not?

For those who think custom attributes are a good thing: what are some things to keep in mind when using them?

For those who think custom attributes are bad thing: what alternatives do you use to accomplish something similar?

Update: I'm mostly interested in the reasoning behind the various methods, as well as points as to why one method is better than another. I think we can all come up with 4-5 different ways to accomplish the same thing. (hidden elements, inline scripts, extra classes, parsing info from ids, etc).

Update 2: It seems that the HTML 5 data- attribute feature has a lot of support here (and I tend to agree, it looks like a solid option). So far I haven't seen much in the way of rebuttals for this suggestion. Are there any issues/pitfalls to worry about using this approach? Or is it simply a 'harmless' invalidation of the current W3C specs?

Recently I have been reading more and more about people using custom attributes in their HTML tags, mainly for the purpose of embedding some extra bits of data for use in javascript code.

I was hoping to gather some feedback on whether or not using custom attributes is a good practice, and also what some alternatives are.

It seems like it can really simplify both server side and client side code, but it also isn't W3C compliant.

Should we be making use of custom HTML attributes in our web apps? Why or why not?

For those who think custom attributes are a good thing: what are some things to keep in mind when using them?

For those who think custom attributes are bad thing: what alternatives do you use to accomplish something similar?

Update: I'm mostly interested in the reasoning behind the various methods, as well as points as to why one method is better than another. I think we can all come up with 4-5 different ways to accomplish the same thing. (hidden elements, inline scripts, extra classes, parsing info from ids, etc).

Update 2: It seems that the HTML 5 data- attribute feature has a lot of support here (and I tend to agree, it looks like a solid option). So far I haven't seen much in the way of rebuttals for this suggestion. Are there any issues/pitfalls to worry about using this approach? Or is it simply a 'harmless' invalidation of the current W3C specs?

Share Improve this question edited Aug 31, 2016 at 9:41 surfmuggle 5,9168 gold badges55 silver badges89 bronze badges asked Jun 14, 2009 at 3:52 TM.TM. 111k34 gold badges124 silver badges128 bronze badges 9
  • Honestly, my initial stance is that they're not such a bad thing, which can be rather controversial with the purists. I feel like I really need to sit down and evaluate all the options available to properly back this up, though, thus the need to write the long essay. – Paolo Bergantino Commented Jun 14, 2009 at 4:35
  • To do that you may need only some counter-example[s]: of what you're trying to implement, how it's convenient to do that with custom attributes, and why that solution better and not worse than other solutions without custom attributes. – ChrisW Commented Jun 14, 2009 at 4:40
  • @ChrisW I am asking mostly out of interest, not out of some specific application. – TM. Commented Jun 14, 2009 at 4:46
  • Well, there's a lot of options for getting the data to the client side: hidden input fields, hidden definition lists, classes, metadata plugins, having a huge Javascript dictionary (object) with all the data mapping separately, custom attributes, data attributes (HTML5), etc. I want to explore all of these, consider their merits, their pitfalls, and finally reach a conclusion. This post did finally get me to start writing this. :) Should be done sometime before 2010. – Paolo Bergantino Commented Jun 14, 2009 at 4:47
  • 2 @Paolo you can't just say you wrote an essay answering this question without giving us the link. Not cool. – Connell Commented Nov 4, 2011 at 14:37
 |  Show 4 more comments

15 Answers 15

Reset to default 261

HTML 5 explicitly allows custom attributes that begin with data. So, for example, <p data-date-changed="Jan 24 5:23 p.m.">Hello</p> is valid. Since it's officially supported by a standard, I think this is the best option for custom attributes. And it doesn't require you to overload other attributes with hacks, so your HTML can stay semantic.

Source: http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes

Here's a technique I've been using recently:

<div id="someelement">

    <!-- {
        someRandomData: {a:1,b:2},
        someString: "Foo"
    } -->

    <div>... other regular content...</div>
</div>

The comment-object ties to the parent element (i.e. #someelement).

Here's the parser: http://pastie.org/511358

To get the data for any particular element simply call parseData with a reference to that element passed as the only argument:

var myElem = document.getElementById('someelement');

var data = parseData( myElem );

data.someRandomData.a; // <= Access the object staight away

It can be more succinct than that:

<li id="foo">
    <!--{specialID:245}-->
    ... content ...
</li>

Access it:

parseData( document.getElementById('foo') ).specialID; // <= 245

The only disadvantage of using this is that it cannot be used with self-closing elements (e.g. <img/>), since the comments must be within the element to be considered as that element's data.


EDIT:

Notable benefits of this technique:

  • Easy to implement
  • Does not invalidate HTML/XHTML
  • Easy to use/understand (basic JSON notation)
  • Unobtrusive and semantically cleaner than most alternatives

Here's the parser code (copied from the http://pastie.org/511358 hyperlink above, in case it ever becomes unavailable on pastie.org):

var parseData = (function(){

    var getAllComments = function(context) {

            var ret = [],
                node = context.firstChild;

            if (!node) { return ret; }

            do {
                if (node.nodeType === 8) {
                    ret[ret.length] = node;
                }
                if (node.nodeType === 1) {
                    ret = ret.concat( getAllComments(node) );
                }
            } while( node = node.nextSibling );

            return ret;

        },
        cache = [0],
        expando = 'data' + +new Date(),
        data = function(node) {

            var cacheIndex = node[expando],
                nextCacheIndex = cache.length;

            if(!cacheIndex) {
                cacheIndex = node[expando] = nextCacheIndex;
                cache[cacheIndex] = {};
            }

            return cache[cacheIndex];

        };

    return function(context) {

        context = context || document.documentElement;

        if ( data(context) && data(context).commentJSON ) {
            return data(context).commentJSON;
        }

        var comments = getAllComments(context),
            len = comments.length,
            comment, cData;

        while (len--) {
            comment = comments[len];
            cData = comment.data.replace(/\n|\r\n/g, '');
            if ( /^\s*?\{.+\}\s*?$/.test(cData) ) {
                try {
                    data(comment.parentNode).commentJSON =
                        (new Function('return ' + cData + ';'))();
                } catch(e) {}
            }
        }

        return data(context).commentJSON || true;

    };

})();

You can create any attribute if you specify a schema for your page.

For example:

Addthis

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:addthis="http://www.addthis.com/help/api-spec">
...
<a addthis:title="" addthis:url="" ...>

Facebook (even tags)

<html xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml">
...
<fb:like href="http://developers.facebook.com/" width="450" height="80"/>

The easiest way to avoid use of custom attributes is to use existing attributes.

use meaningful, relevant class names.
For example, do something like: type='book' and type='cd', to represent books and cds. Classes are much better for representing what something IS.

e.g. class='book'

I have used custom attributes in the past, but honestly, there really isn't a need to for them if you make use of existing attributes in a semantically meaningful way.

To give a more concrete example, let's say you have a site giving links to different kinds of stores. You could use the following:

<a href='wherever.html' id='bookstore12' class='book store'>Molly's books</a>
<a href='whereverelse.html' id='cdstore3' class='cd store'>James' Music</a>

css styling could use classes like:

.store { }
.cd.store { }
.book.store { }

In the above example we see that both are links to stores (as opposed to the other unrelated links on the site) and one is a cd store, and the other is a book store.

Embed the data in the dom and use metadata for jQuery.

All the good plug-ins support the metadata plugin(allowing per tag options).

It also allows infinitely complex data/data structures, as well as key-value pairs.

<li class="someclass {'some': 'random,'json':'data'} anotherclass">...</li>

OR

<li class="someclass" data="{'some':'random', 'json': 'data'}">...</li>

OR

<li class="someclass"><script type="data">{"some":"random","json":"data"}</script> ...</li>

Then get the data like so:

var data = $('li.someclass').metadata();
if ( data.some && data.some == 'random' )
alert('It Worked!');

I see no problem in using existing XHTML features without breaking anything or extending your namespace. Let's take a look at a small example:

<div id="some_content">
 <p>Hi!</p>
</div>

How to add additional information to some_content without additional attributes? What about adding another tag like the following?

<div id="some_content">
 <div id="some_content_extended" class="hidden"><p>Some alternative content.</p></div>
 <p>Hi!</p>
</div>

It keeps the relation via a well defined id/extension "_extended" of your choice and by its position in the hierarchy. I often use this approach together with jQuery and without actually using Ajax like techniques.

Nay. Try something like this instead:

<div id="foo"/>

<script type="text/javascript">
  document.getElementById('foo').myProperty = 'W00 H00! I can add JS properties to DOM nodes without using custom attributes!';
</script>

I'm not doing using custom attributes, because I'm outputing XHTML, because I want the data to be machine-readable by 3rd-party software (although, I could extend the XHTML schema if I wanted to).

As an alternative to custom attributes, mostly I'm finding the id and class attributes (e.g. as mentioned in other answers) sufficient.

Also, consider this:

  • If the extra data is to be human-readable as well as machine-readable, then it needs to be encoded using (visible) HTML tags and text instead of as custom attributes.

  • If it doesn't need to be human readable, then perhaps it can be encoded using invisible HTML tags and text.

Some people make an exception: they allow custom attributes, added to the DOM by Javascript on the client side at run-time. They reckon this is OK: because the custom attributes are only added to the DOM at run-time, the HTML contains no custom attributes.

We've made a web-based editor that understands a subset of HTML - a very strict subset (that understood nearly universally by mail clients). We need to express things like <td width="@INSWIDTH_42@"> in the database, but we can't have that in the DOM, otherwise the browser where the editor runs, freaks out (or is more likely to freak out than it is likely to freak out over custom attributes). We wanted drag-and-drop, so putting it purely in the DOM was out, as was jquery's .data() (the extra data didn't get copied properly). We probably also needed the extra data to come along for the ride in .html(). In the end we settled on using <td width="1234" rs-width="@INSWIDTH_42@"> during the editing process, and then when we POST it all, we remove width and do a regex search-and-destroy s/rs-width=/width=/g.

At first the guy writing most of this was the validation-nazi on this issue and tried everything to avoid our custom attribute, but in the end acquiesced when nothing else seemed to work for ALL our requirements. It helped when he realized that the custom attribute would never appear in an email We did consider encoding our extra data in class, but decided that would be the greater of two evils.

Personally, I prefer to have things clean and passing validators etc., but as a company employee I have to remember that my primary responsibility is advancing the company's cause (making as much money as quickly as possible), not that of my egotistical desire for technical purity. Tools should work for us; not us for them.

I know people are against it, but I came up with a super short solution for this. If you want to use a custom attribute like "mine" so for example:

<a href="test.html" mine-one="great" mine-two="awesome">Test</a>

Then you can run this code to get an object back just like jquery.data() does.

var custom_props = {} ;
$.each($(".selector")[0].attributes, function(i,x) {
    if (this.specified && x.name.indexOf("mine-") !== -1) 
        self.new_settings[x.name.replace("modal-","")] = x.value;
});

For complex web apps, I drop custom attributes all over the place.

For more public facing pages I use the "rel" attribute and dump all my data there in JSON and then decode it with MooTools or jQuery:

<a rel="{color:red, awesome:true, food: tacos}">blah</a>

I'm trying to stick with HTML 5 data attribute lately just to "prepare", but it hasn't come naturally yet.

Spec: Create an ASP.NET TextBox control which dynamically auto-formats its text as a number, according to properties "DecimalSeparator" and "ThousandsSeparator", using JavaScript.


One way to transfer these properties from the control to JavaScript is to have the control render out custom properties:

<input type="text" id="" decimalseparator="." thousandsseparator="," />

Custom properties are easily accessible by JavaScript. And whilst a page using elements with custom properties won't validate, the rendering of that page won't be affected.


I only use this approach when I want to associate simple types like strings and integers to HTML elements for use with JavaScript. If I want to make HTML elements easier to identify, I'll make use of the class and id properties.

I use custom fields all the time for example <a i="" .... Then reference to i with jquery. Invalid html , yes. It works well, yes.

Contrary to answers which say custom attributes won't validate:

Custom attributes will validate.

So will custom tags, as long as the custom tags are lowercase and hyphenated.

Try this in any validator. It will validate.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Custom Test</title>
    </head>
    <body>
        <dog-cat PIANO="yellow">test</dog-cat>
    </body>
</html>

Some validators:

https://appdevtools.com/html-validator

https://www.freeformatter.com/html-validator.html

https://validator.w3.org/nu/

The question is: Is it safe? Will it break later?

Custom Tags

No hyphenated tags exist. I believe that W3C will never use a hyphenated tag. And if they did, as long as you use an uncommon prefix, you'll never see a conflict. Eg.<johny-mytag>.

Custom Attributes

There are hyphenated HTML attributes. But the HTML spec promises never to use an attribute starting with data-. So data-myattrib is guaranteed to be safe. However, i believe that W3C will never introduce any attribute that starts with johny-. As long as your prefix is unusual, you'll never see a conflict.

Custom attributes, in my humble opinion, should not be used as they do not validate. Alternative to that, you can define many classes for a single element like:

<div class='class1 class2 class3'>
    Lorem ipsum
</div>

本文标签: javascriptCustom attributesYea or nayStack Overflow