Additions to HTML tables that enable sorting.

This specification is an experimental breakup of the HTML specification. You can see the full list on the index page and take part in the discussion in the repository.

Table sorting model

The sortable attribute on table elements is a boolean attribute. When present, it indicates that the user agent is to allow the user to sort the table.

To make a column sortable in a table with a thead, the column needs to have th element that does not span multiple columns in a thead above any rows that it is to sort.

To make a column sortable in a table without a thead, the column needs to have th element that does not span multiple columns in the first tr element of the table, where that tr element is not in a tfoot.

When the user selects a column by which to sort, the user agent sets the th element's sorted attribute. This attribute can also be set manually, to indicate that the table should be automatically sorted, even when scripts modify the page on when the page is loaded.

The sorted attribute, if specified, must have a value that is a set of space-separated tokens consisting of optionally a token whose value is an ASCII case-insensitive match for the string "reversed", and optionally a token whose value is a valid non-negative integer greater than zero, in either order.

In other words, ignoring spaces and case, the sorted attribute's value can be empty, "reversed", "1", "reversed 1", or "1 reversed", where "1" is any number equal to or greater than 1.

While one or more th elements in the table have a sorted attribute, the user agent will keep the table's data rows sorted. The value of the attribute controls how the column is used in determining the sort order. The reversed keyword means that the column sort direction is reversed, rather than normal, which is the default if the keyword is omitted. The number, if present, indicates the column key ordinality; if the number is omitted, the column is the primary key, as if the value 1 had been specified.

Thus, sorted="1" indicates the table's primary key, sorted="2" its secondary key, and so forth.


A sorting-capable th element is a th element that matches all the following conditions simultaneously:

In other words, each column can have one sorting-capable th element; this will be the highest th in a thead that spans no other columns, or, if there is no thead, the th in the first row (that is not in a tfoot), assuming it spans no columns.

The sorting-capable th elements of the table element table are the sorting-capable th elements whose cell's table is table.

A table element table is a sorting-capable table element if there are one or more sorting-capable th elements of the table element table.

A th element is a sorting-enabled th element if it is a sorting-capable th element and it has a sorted attribute.

The sorting-enabled th elements of the table element table are the sorting-enabled th elements whose cell's table is table.

A table element table is a sorting-enabled table element if there are one or more sorting-capable th elements of the table element table, and at least one of them is a sorting-enabled th element (i.e. at least one has a sorted attribute).

A table element is a table element with a user-agent exposed sorting interface if it is a sorting-capable table element and has a sortable attribute specified.

A sorting interface th element is a sorting-capable th element whose cell's table is a table element with a user-agent exposed sorting interface.


Each table element has a currently-sorting flag, which must initially be false.


The sorted attribute must not be specified on th elements that are not sorting-capable th elements. The sortable attribute must not be specified on table elements that are not sorting-capable table elements.

To determine a th element's sorted attribute's column sort direction and column key ordinality, user agents must use the following algorithm:

  1. Let direction be normal.

  2. Let have explicit direction be false.

  3. Let ordinality be 1.

  4. Let have explicit ordinality be false.

  5. Let tokens be the result of splitting the attribute's value on spaces.

  6. For each token token in tokens, run the appropriate steps from the following list:

    If have explicit direction is false and token is an ASCII case-insensitive match for the string "reversed"

    Let direction be reversed and have explicit direction be true.

    If have explicit ordinality is false

    Parse token as an integer. If this resulted in an error or the value zero, then ignore the token. Otherwise, set ordinality to the parsed value, and set have explicit ordinality to true.

    Otherwise

    Ignore the token.

  7. The column sort direction is the value of direction, and the column key ordinality is the value of ordinality.

A table must not have two th elements whose sorted attribute have the same column key ordinality.


The table sorting algorithm, which is applied to a table, is as follows:

  1. Let table be the table element being sorted.

  2. If table's currently-sorting flag is true, then abort these steps.

  3. Set table's currently-sorting flag to true.

  4. Fire a simple event named sort that is cancelable at table.

  5. If the event fired in the previous step was canceled, then jump to the step labeled end below.

  6. If table is not now a sorting-enabled table element, then jump to the step labeled end below.

    Even if table was a sorting-enabled table element when the algorithm was invoked, the DOM might have been entirely changed by the event handlers for the sort event, so this has to be verified at this stage, not earlier.

  7. Let key heading cells be the sorting-enabled th elements of the table element table.

  8. Sort key heading cells in ascending order of the column key ordinality of their sorted attributes, with those having the same column key ordinality being sorted in tree order.

  9. Let row collection cursor be a pointer to an element, initially pointing at the first child of table that is after table's first thead, if any, and that is either a tbody or a tr element, assuming there is one. If there is no such child, then jump to the step labeled end below.

  10. If table has no row group corresponding to a thead element, then set ignore first group to true. Otherwise, set it to false.

  11. Run these substeps:

    1. Row loop: Let rows be an empty list of tr elements.

    2. Run these substeps:

      1. Run the appropriate steps from the following list:

        If row collection cursor points to a tr element
        1. Collect: Append the element pointed to by row collection cursor to rows.

        2. If there are no tr or tbody children of table that are later siblings of the element pointed to by row collection cursor, or if the next such child is a tbody element, then jump to the step labeled group below.

        3. Let row collection cursor point to the next tr child of table that is a later sibling of the element pointed to by row collection cursor.

        4. Jump back to the step labeled collect above.

        If row collection cursor points to a tbody element
        1. Place all the tr element children of the element pointed to by row collection cursor into rows, in tree order.

        2. If rows is empty, jump to the step labeled increment loop below.

      2. Group: Let groups be an empty list of groups of tr elements.

      3. Let group be an empty group of tr elements.

      4. Let group cursor be a pointer to an element, initially pointing at the first tr element in rows.

      5. Run these substeps:

        1. Start group: Let pending rows in group be 1.

        2. Run these substeps:

          1. Group loop: Append the tr element pointed to by group cursor to group.

          2. If there are any cells whose highest row's element is the one pointed to by group cursor, then let tallest height be the number of rows covered by the tallest such cell.

          3. If tallest height is greater than pending rows in group then set pending rows in group to tallest height.

          4. Decrement pending rows in group by one.

          5. Let group cursor point to the next tr element in rows, if any; otherwise, let it be null.

          6. If group cursor is not null and pending rows in group is not zero, jump back to the step labeled group loop.

        3. Append a new group to groups consisting of the tr elements in group.

        4. Empty group.

        5. If group cursor is not null, then jump back to the step labeled start group.

      6. If ignore first group is true, then drop the first group in groups and set ignore first group to false.

      7. Run these steps:

        1. Drop leading header groups: If groups is now empty, jump to the step labeled increment loop below.

        2. If the first group of groups consists of tr elements whose element children are all th elements, then drop the first group in groups and jump back to the previous step (labeled drop leading header groups).

      8. Let insertion point be a placeholder in a DOM tree, which can be used to reinsert nodes at a specific point in the DOM. Insert insertion point into the parent of the first tr element of the first group in groups, immediately before that tr element.

      9. Sort the groups in groups, using the following algorithm to decide the relative order of any two groups a and b (the algorithm either returns that a comes before b, or that b comes before a):

        1. Let key index be an index into key heading cells, initially denoting the first element in the list.

        2. Let direction be a sort direction, initially ascending. Its other possible value is descending. When direction is toggled, that means that if its value is ascending, it must be changed to descending, and when its value is descending, it must be changed to ascending.

        3. Run these substeps:

          1. Column loop: Let th be the key indexth th in key heading cells.

          2. If th's sorted attribute's column sort direction is reversed, then toggle direction.

          3. Let tentative order be the result of comparing two row groups using the th element th, with a and b as the rows.

          4. If tentative order is not "equal", then jump to the step labeled return below.

          5. Increment key index.

          6. If key index still denotes a th element in key heading cells, then jump back to the step above labeled column loop.

        4. If a's tr elements precede b's in tree order, then let tentative order be "a before b". Otherwise, let tentative order be "b before a".

        5. Return: Return the relative order given by the matching option from the following list:

          If direction is ascending and tentative order is "a before b"
          Return that a comes before b.
          If direction is ascending and tentative order is "b before a"
          Return that b comes before a.
          If direction is descending and tentative order is "a before b"
          Return that b comes before a.
          If direction is descending and tentative order is "b before a"
          Return that a comes before b.

        When the user agent is required to compare two row groups using the th element th, with a and b being the two row groups respectively, the user agent must run the following steps:

        1. Let x be the x-coordinate of the slots that th covers in its table.

        2. Let cella be the element corresponding to the cell in the first row of group a that covers the slot in that row whose x-coordinate is x.

          Let cellb be the element corresponding to the cell in the first row of group b that covers the slot in that row whose x-coordinate is x.

          In either case, if there's no cell that actually covers the slot, then use the value null instead.

        3. Let typea and valuea be the type and value of the cell cella, as defined below.

          Let typeb and valueb be the type and value of the cell cellb, as defined below.

          The type and value of the cell cell are computed as follows.

          1. If cell is null, then the type is "string" and the value is the empty string; abort these steps.

          2. If, ignoring inter-element whitespace and nodes other than Element and Text nodes, cell has only one child and that child is a data element, then the value is the value of that data element's value attribute, if there is one, or the empty string otherwise; the type is "string".

          3. If, ignoring inter-element whitespace and nodes other than Element and Text nodes, cell has only one child and that child is a progress element, then the value is the value of that progress element's value attribute, if there is one, or the empty string otherwise; the type is "string".

          4. If, ignoring inter-element whitespace and nodes other than Element and Text nodes, cell has only one child and that child is a meter element, then the value is the value of that meter element's value attribute, if there is one, or the empty string otherwise; the type is "string".

          5. If, ignoring inter-element whitespace and nodes other than Element and Text nodes, cell has only one child and that child is a time element, then the value is the machine-readable equivalent of the element's contents, if any, and the type is the kind of value that is thus obtained (a month, a date, a yearless date, a time, a local date and time, a time-zone offset, a global date and time, a week, a year, or a duration); abort these steps after completing this one.

            If there is no machine-readable equivalent, then the type is "string" and the value is the empty string.

            If the type is a month, a date, a week, or a year, then change the value to be the instant in time (with no time zone) that describes the earliest moment that the value represents, and change the type to be a local date and time.

            For example, if the cell was <td><time>2011-11</time> then for sorting purposes the value is interpreted as "2011-11-01T00:00:00.000" and the type is treated as a local date and time rather than a month.

            Similarly, if the cell was <td><time datetime="2014">MMXIV</time> then for sorting purposes the value is interpreted as "2014-01-01T00:00:00.000" and the type is treated as a local date and time rather than a year.

          6. The value is the element's textContent. The type is "string".

        4. If typea and typeb are not equal, then: return "a before b" if typea is earlier in the following list than typeb, otherwise, return "b before a"; then, abort these steps.

          1. time
          2. yearless date
          3. local date and time
          4. global date and time
          5. time-zone offset
          6. duration
          7. "string"
        5. If valuea and valueb are equal, then return "equal" and abort these steps.

        6. If typea and typeb are not "string", then: if valuea is earlier than valueb then return "a before b" and abort these steps, otherwise, return "b before a" and abort these steps.

          Values sort in their natural order, with the following additional constraints:

          For time values, 00:00:00.000 is the earliest value and 23:59:59.999 is the latest value.

          For yearless date values, 01-01 is the earliest value and 12-31 is the latest value; 02-28 is earlier than 02-29 which is earlier than 03-01.

          Values that are local date and time compare as if they were in the same time zone.

          For time-zone offset values, -23:59 is the earliest value and +23:59 is the latest value.

        7. Let componentsa be the result of parsing the sort key valuea.

          Let componentsb be the result of parsing the sort key valueb.

          As described below, componentsa and componentsb are tuples consisting of a list of n numbers, a list of n number strings, a list of n+1 non-numeric strings, and a list of 2n+1 raw strings, for any non-negative integer value of n (zero or more).

        8. Let order be the result of a locale-specific string comparison of componentsa's first non-numeric string and componentsb's first non-numeric string, in the context of th.

          If order is not "equal" then return order and abort these steps.

        9. If componentsa and componentsb both have exactly one number, then run these substeps:

          1. If componentsa's number is less than componentsb's number, return "a before b".

            If componentsb's number is less than componentsa's number, return "b before a".

          2. Let order be the result of a locale-specific string comparison of componentsa's second non-numeric string and componentsb's second non-numeric string, in the context of th.

            If order is not "equal" then return order and abort these steps.

          3. Let order be the result of a locale-specific string comparison of componentsa's number string and componentsb's number string, in the context of th.

            If order is not "equal" then return order and abort these steps.

          Otherwise, run these substeps:

          1. If componentsa has zero numbers but componentsb has more than zero numbers, return "a before b".

            If componentsb has zero numbers but componentsa has more than zero numbers, return "b before a".

          2. If componentsa has one number, return "a before b".

            If componentsb has one number, return "b before a".

          3. If componentsa and componentsb have more than one number, run these substeps:

            1. Let count be the smaller of the number of numbers in componentsa and the number of numbers in componentsb.

            2. For each number in componentsa and componentsb from the first to the countth, in order: if componentsa's number is less than componentsb's number, then return "a before b" and abort these steps; otherwise, if componentsb's number is less than componentsa's number, return "b before a" and abort these steps.

            3. If componentsa has fewer numbers than componentsb, return "a before b" and abort these steps.

              If componentsb has fewer numbers than componentsa, return "b before a" and abort these steps.

            4. Let index be zero.

            5. String loop: Let order be the result of a locale-specific string comparison of componentsa's indexth number string and componentsb's indexth number string, in the context of th.

              If order is not "equal" then return order and abort these steps.

            6. Increment index.

            7. Let order be the result of a locale-specific string comparison of componentsa's indexth separator string and componentsb's indexth separator string, in the context of th.

              If order is not "equal" then return order and abort these steps.

            8. If index is less than the number of numbers in componentsa and componentsb, jump back to the step labeled string loop.

        10. Let index be zero.

        11. Run these substeps:

          1. Final loop: Let order be the result of a raw string comparison of componentsa's nth raw string and componentsb's nth raw string.

            If order is not "equal" then return order and abort these steps.

          2. Increment index.

          3. If index is less than the number of raw strings in componentsa and componentsb, jump back to the step labeled final loop.

        12. Return "equal".

      10. Let new order be a list of tr elements consisting of the tr elements of all the groups in the newly ordered groups, with the tr elements being in the same order as the groups to which they belong are in groups, and the tr elements within each such group themselves being ordered in tree order.

      11. Remove all the tr elements in new order from their parents, in tree order.

      12. Insert all the tr elements in new order into the DOM at the location of insertion point, in the order these elements are found in new order.

      13. Remove insertion point from the DOM.

    3. Increment loop: If there are no tr or tbody children of table that are later siblings of the element pointed to by row collection cursor, then jump to the step labeled end below.

    4. Let row collection cursor point to the next tr or tbody child of table that is a later sibling of the element pointed to by row collection cursor.

    5. Jump back to the step labeled row loop above.

  12. End: Set table's currently-sorting flag to false.

When a user agent is to parse the sort key value, it must run the following steps. These return a tuple consisting of a list of n numbers, a list of n number strings, a list of n+1 non-numeric strings, and a list of 2n+1 raw strings, respectively, for any non-negative integer value of n (zero or more).

  1. Let raw strings be a list of strings initially containing just one entry, an empty string.

  2. Let negatives prejudiced be false.

    Let decimals prejudiced be false.

    Let exponents prejudiced be false.

  3. Let buffer be the empty string.

    Let index be zero.

    Let mode be "separator".

    When a subsequent step in this algorithm says to push the buffer, the user agent must run the following substeps:

    1. Add an entry to raw strings that consists of the value of buffer.

    2. Add an entry to raw strings that is the empty string.

    3. Decrement index by one.

    4. Set mode to "separator".

  4. Let checkpoint buffer be the empty string.

    Let checkpoint index be zero.

    When a subsequent step in this algorithm says to checkpoint, the user agent must run the following substeps:

    1. Set the checkpoint buffer to the value of buffer.

    2. Set the checkpoint index to the value of index.

    When a subsequent step in this algorithm says to push the checkpoint, the user agent must run the following substeps:

    1. Add an entry to raw strings that consists of the value of checkpoint buffer.

    2. Add an entry to raw strings that is the empty string.

    3. Decrement index by one.

    4. Set mode to "separator".

  5. Run through the following steps repeatedly until the condition in the last step is met.

    1. Top of loop: If index is equal to or greater than the number of characters in value, let c be EOF. Otherwise, let c be the indexth character in value.

    2. Run the appropriate steps from the following list:

      If mode is "separator"

      Run the appropriate substeps from the following list:

      If c is a space character

      Set negatives prejudiced to false.

      Set decimals prejudiced to false.

      Set exponents prejudiced to false.

      Append c to the last entry in raw strings.

      If c is a U+002D HYPHEN-MINUS character (-) and negatives prejudiced is false

      Set buffer to the value of c.

      Set mode to "negative".

      If c is a U+002E FULL STOP character (.) and decimals prejudiced is false

      Set buffer to the value of c.

      Set mode to "leading-decimal".

      If c is an ASCII digit

      Set buffer to the value of c.

      Set mode to "integral".

      If c is an uppercase ASCII letter or a lowercase ASCII letter

      Set exponents prejudiced to true.

      Append c to the last entry in raw strings.

      If c is EOF

      Do nothing.

      Otherwise

      Append c to the last entry in raw strings.

      If mode is "negative"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Append buffer to the last entry in raw strings.

      Append c to the last entry in raw strings.

      Set mode to "separator".

      If c is a U+002E FULL STOP character (.) and decimals prejudiced is false

      Append c to buffer.

      Set mode to "leading-decimal".

      If c is an ASCII digit

      Append c to buffer.

      Set mode to "integral".

      Otherwise

      Append buffer to the last entry in raw strings.

      Decrement index by one.

      Set mode to "separator".

      If mode is "integral"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Push the buffer.

      If c is a U+002E FULL STOP character (.) and decimals prejudiced is false

      Checkpoint.

      Append c to buffer.

      Set mode to "decimal".

      If c is an ASCII digit

      Append c to the last entry in raw strings.

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character and exponents prejudiced is false

      Checkpoint.

      Append c to buffer.

      Set mode to "exponent".

      Otherwise

      Push the buffer.

      If mode is "leading-decimal"

      Run the appropriate substeps from the following list:

      If c is an ASCII digit

      Append c to buffer.

      Set mode to "decimal".

      Otherwise

      Append buffer to the last entry in raw strings.

      Decrement index by one.

      Set mode to "separator".

      If mode is "decimal"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Push the buffer.

      If c is a U+002E FULL STOP character (.) and any of the characters in value past the indexth character are ASCII digits

      Set decimals prejudiced to true.

      Push the checkpoint.

      If c is a U+002E FULL STOP character (.) and none of the characters in value past the indexth character are ASCII digits

      Push the buffer.

      If c is an ASCII digit

      Append c to buffer.

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character and exponents prejudiced is false

      Checkpoint.

      Append c to buffer.

      Set mode to "exponent".

      Otherwise

      Push the buffer.

      If mode is "exponent"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-) and negatives prejudiced is false

      Append c to buffer.

      Set mode to "exponent-negative".

      If c is a U+002E FULL STOP character (.)

      Set decimals prejudiced to true.

      Push the checkpoint.

      If c is an ASCII digit

      Append c to buffer.

      Set mode to "exponent-number".

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character

      Set exponents prejudiced to true.

      Push the checkpoint.

      Otherwise

      Push the checkpoint.

      If mode is "exponent-negative"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Push the checkpoint.

      If c is a U+002E FULL STOP character (.)

      Set decimals prejudiced to true.

      Push the checkpoint.

      If c is an ASCII digit

      Append c to buffer.

      Set mode to "exponent-negative-number".

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character

      Set exponents prejudiced to true.

      Push the checkpoint.

      Otherwise

      Push the checkpoint.

      If mode is "exponent-number"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Push the buffer.

      If c is a U+002E FULL STOP character (.)

      Set decimals prejudiced to true.

      Push the checkpoint.

      If c is an ASCII digit

      Append c to buffer.

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character

      Set exponents prejudiced to true.

      Push the checkpoint.

      Otherwise

      Push the buffer.

      If mode is "exponent-negative-number"

      Run the appropriate substeps from the following list:

      If c is a U+002D HYPHEN-MINUS character (-)

      Set negatives prejudiced to true.

      Push the checkpoint.

      If c is a U+002E FULL STOP character (.)

      Set decimals prejudiced to true.

      Push the checkpoint.

      If c is an ASCII digit

      Append c to buffer.

      If c is a U+0045 LATIN CAPITAL LETTER E character or a U+0065 LATIN SMALL LETTER E character

      Set exponents prejudiced to true.

      Push the checkpoint.

      Otherwise

      Push the buffer.

    3. Increment index by one.

    4. If index is greater than the number of characters in value, stop repeating these substeps and continue along the overall steps. Otherwise, return to the step labeled top of loop.

  6. Let numbers be an empty list.

    Let number strings be an empty list.

    Let non-numeric strings be an empty list.

  7. For each even-numbered entry in raw strings, in order, starting from the first entry (numbered 0), append an entry to non-numeric strings that consists of the result of trimming and collapsing the value of the entry.

  8. If raw strings has more than one entry, then, for each odd-numbered entry in raw strings, in order, starting from the second entry (numbered 1), append an entry to number strings that consists of the value of the entry, and append an entry to number strings that consists of the result of parsing the value of the entry using the rules for parsing floating-point number values.

  9. Return numbers, number strings, non-numeric strings, and raw strings respectively.

When the user agent is required by the step above to perform a locale-specific string comparison of two strings a and b in the context of an element e, the user agent must apply the Unicode Collation Algorithm, using the Default Unicode Collation Element Table as customised for the language of the element e in the Common Locale Data Repository, to the strings a and b, ignoring case. If the result of this algorithm places a first, then return "a before b"; if it places b first, then return "b before a"; otherwise, if they compare as equal, then return "equal". [[!UCA]] [[!CLDR]]

When the user agent is required by the step above to perform a raw string comparison of two strings a and b, the user agent must apply the Unicode Collation Algorithm, using the Default Unicode Collation Element Table without customizations, to the strings a and b. If the result of this algorithm places a first, then return "a before b"; if it places b first, then return "b before a"; otherwise, if they compare as equal, then return "equal". [[!UCA]]

Where the steps above refer to trimming and collapsing a string value, it means running the following algorithm:

  1. Strip leading and trailing whitespace from value.

  2. Replace any sequence of one or more space characters in value with a single U+0020 SPACE character.


When any of the descendants of a sorting-enabled table element change in any way (including attributes changing), and when a table element becomes a sorting-enabled table element, the table element is said to become a table with a pending sort. When a table element becomes a table with a pending sort, the user agent must queue a microtask that applies the table sorting algorithm to that table, and then flags the table as no longer being a table with a pending sort.


When the user agent is to set the sort key to a th element target, it must run the following algorithm:

  1. Let table be the table of the table of which target is a header cell.

  2. If th is a sorting-enabled th element whose column key ordinality is 1, then: if its column sort direction is normal, set that element's sorted attribute to the string "reversed", otherwise, set it to the empty string; then, abort these steps.

  3. Let current headers be the sorting-enabled th elements of the table element table, excluding target.

  4. Sort current headers by their sorted attributes' column key ordinality, in ascending order, with elements that have the same column key ordinality being sorted in tree order.

  5. Let level be 2.

  6. For each th element th in current headers, in order, run the following substeps:

    1. If th's sorted attribute's column sort direction is normal, then set th's sorted attribute to a valid integer whose value is level. Otherwise, set it to the concatenation of the string "reversed", a U+0020 SPACE character, and a valid integer whose value is level.

    2. Increment level by 1.

  7. Set target's sorted attribute to the empty string.


The activation behaviour of a sorting interface th element is to set the sort key to the th element.

The table will be sorted the next time the user agent performs a microtask checkpoint.

th . sort()

Act as if the user had indicated that this was to be the new primary sort column.

The table won't actually be sorted until the script terminates.

table . stopSorting()

Removes all the sorted attributes that are causing the table to automatically sort its contents, if any.

The th element's sort() method, when invoked, must run the following steps:

  1. If the th element is not a sorting-capable th element, then abort these steps.

  2. Set the sort key to the th element.

    The table will be sorted the next time the user agent performs a microtask checkpoint.

The table element's stopSorting() method, when invoked, must remove the sorted attribute of all the sorting-enabled th elements of the table element on which the method was invoked.