Please refer the Before attribute name state section of the HTML5 Spec:
- U+0009 CHARACTER TABULATION (tab)
- U+000A LINE FEED (LF)
- U+000C FORM FEED (FF)
- U+0020 SPACE
- Ignore the character.
- U+002F SOLIDUS (/)
Switch to the self-closing start tag state.
- U+003E GREATER-THAN SIGN (>)
Switch to the data state. Emit the current tag token.
Uppercase ASCII letter
- Start a new attribute in the current tag token. Set that attribute's name to the lowercase version of the current input character (add 0x0020 to the character's code point), and its value to the empty string. Switch to the attribute name state.
- U+0000 NULL
- Parse error. Start a new attribute in the current tag token. Set that attribute's name to a U+FFFD REPLACEMENT CHARACTER character, and its value to the empty string. Switch to the attribute name state.
- U+0022 QUOTATION MARK (")
- U+0027 APOSTROPHE (')
- U+003C LESS-THAN SIGN (<)
- U+003D EQUALS SIGN (=)
- Parse error. Treat it as per the "anything else" entry below.
- EOF
Parse error. Switch to the data state. Reconsume the EOF character.
- Anything else
Start a new attribute in the current tag token. Set that attribute's name to the current input character, and its value to the empty string. Switch to the attribute name state.
In simple words:
It says all characters except tab, line feed, form feed, space, solidus, greater than sign, quotation mark, apostrophe and equals sign will be treated as part of the attribute name. Personally, I wouldn't attempt pushing the edge cases of this though.
Inspired from: What characters are allowed in an HTML attribute name?