Opinionated reset stylesheet that provides a clean slate for styling your html.

  • By Nicolas Cusan
  • Last update: Nov 28, 2022
  • Comments: 11


npm license

Opinionated reset stylesheet that provides a clean slate for styling your html.


  • Ensures consistency across browsers as much as possible
  • Prevents the necessity of reseting user agent styles
  • Prevents style inspector bloat by only targeting what is necessary
  • Removes margins & paddings
  • Removes default font styles and ensures proper inheritance
  • Contributes to the separation of presentation and semantics
  • Sets sensible default styles (see rules)
  • Well suited for utility class libraries and large codebases
  • Made for modern browsers only, therefor small in size (~0.95kb)


$ npm install --save destyle.css


Include destyle.css in the head of your HTML file before your main stylesheet.


Add your base font and color styles to the html or body element in your stylesheet, all other elements will inherit the style from the body.

/* app.css */

html {
  color: #333;
  font: 16px/1.4 "Helvetica Neue", sans-serif;

Styling generated content

It is discouraged to define styles for raw html tags apart from body and html, use classes (or any other selectors / system) for styling.

If you need to create styles for tags generated by a CMS or markdown wrap them in a class (e.g. .type).

.type h1 {
  /* styles */

.type h2 {
  /* styles */
<div class="type">{{ generated_markup_goes_here }}</div>


  • The box model is set to border-box for *, ::before and ::after.
  • The border-style is set to solid for *, ::before and ::after and the border-width is set to 0 (to hide the borders).
  • code, pre, kbd, samp maintain a monospaced font-family.
  • hr is set to be a solid 1px line using border-top that inherits its color from its parent's color property.
  • Inline elements that carry style (b, i, strong, etc.) are not reset.
  • canvas and iframe maintain their default width and height (varies depending on the browser).
  • button, select, textarea and input (except [type='checkbox'] and [type='radio']), are reset using appearance: none.
  • textarea maintains its default height.
  • meter and progress elements are not reset.
  • Replaced content like img, iframe and svg use vertical-align: bottom to prevent alignment issues.
  • Focusable elements retain a focus outline, style depends on browser.


  • range & color inputs are affected by appearance: none but are not completely destyled (varies depending on the browser).
  • button elements that have a fixed height will center its content vertically (can not be reset).



An h1 might need to be bold & large in some context (e.g. at the top of a text page) but might be small and inconspicuous in others (e.g. on a settings page in an app).

Creating two different styles for h1 is made easy, only the properties for the respective desired visual results have to be applied, there is no need to overwrite default styles, all while maintaining semantics.

/* No reseting of the user agent styles necessary,
 * just take care of making things look how you want to. */

/* Bold, large title */
.main-title {
  font-size: 3em;
  margin-bottom: 20px;
  font-weight: bold;

/* Just some padding and gray color, otheriwse looks like normal text */
.secondary-title {
  color: gray;
  padding: 10px;
<!-- article.html -->
<h1 class="main-title">Large title</h1>

<!-- profile.html -->
<h1 class="secondary-title">Small title</h1>

<!-- Looks the same as `h1.secondary-title` -->
<p class="secondary-title">Other small title</p>


button tags have a lot of default styles that can make them cumbersome to use from a styling perspective, especially if they should look like plain links or need to wrap some other content, but button tags are the recommended elements to use as click targets for user interactions. Falling back to using <a href="#"> even with role="button" is not recomended from an accessibility standpoint as screen readers will recognize buttons as interactive elements by default and treat them accordingly. a should be used when there is the need to link to a page via href.

destyle.css resets buttons completely to make them usable as any other element * see note below.

/* Make anything look like a link, even a <button> */
.link {
  color: lightblue;
  text-decoration: underline;

/* Make anything look like a button
 * font styles will be inheritet from the parent */
.btn {
  padding: 0.2em 0.5em;
  border-radius: 0.2em;
  background-color: blue;
  color: white;
  text-align: center;

.block {
  display: block;
  width: 100%;
<!-- Make it look like a link -->
<button class="link">Interactive link</button>

<!-- Make anchor look like a button -->
<a href="page.html" class="btn">Link that looks like a button</a>

<!-- Use as block level element -->
<button class="block">
  <img src="..." alt="..." />


v3.0.2. 2021-12-07

  • Add border-collapse: collapse to tables.

v3.0.0. 2021-09-03

  • Remove IE support 🎉
  • Bring back outline for focusable elements
  • Remove redundant line-height: inherit rule from headings reset
  • Remove redundant text-decoration rule from abbr
  • Added svg selector to replaced content rule
  • Added text-transform: inherit rule to form elements
  • Replaced [disabled] selector with :disabled
  • Removed ::-moz-focus-inner rules for old Firefox versions
  • Improved :-moz-focusring style, no more dotted outline
  • Destyled select:disabled in Chrome
  • Add outline to focused [contenteditable] elements
  • Fixed border color inheritance for table borders in Chrome

v2.0.0. 2020-10-15

  • Add border-style: solid and border-width: 0 to *, ::before, ::after selector. This change might affect how borders are used and therefor is considered a breaking change. The benefit is that simply adding a border-width to an element will display a border without the need to set the border-style explicitly.


Eric Meyer's reset resets properties on elements that do not need it, are unused or even deprecated, this creates bloat in the browser's style inspector which makes developing and debugging less efficient. Normalize.css makes elements look consistent across browsers and it does it well, but it does not remove the user agent's assumptions about how things look. Destyle.css targets both reseting & normalization.

Compare the results here.


This project is heavily inspired by normalize.css and the original reset by Eric Meyer. The source of the test page is from html5-test-page with some additions.

Tested with:





  • 1



    First of all, I love the way of destyling instead of just normalizing, and I'm quite satisfied with your project, thanks.

    However, I have an issue with [contenteditable] : it remains styled similarly to input[type=text].

    Thanks !

  • 2

    Add script for conversion of comments to Sass/Stylus

    I'm a big fan of this approach to resetting, and depending on this package could allow me to eliminate a bunch of stuff I've been maintaining in my own Sass framework until now; however CSS block comments don't get stripped with typical Sass output settings—I prefer to use // style line comments in order to avoid the extra noise in my output, and I think many Sass authors feel the same about the use of block vs line comments.

    The script I've added here simply converts the /* ... */ block comments to the line type, and outputs both .scss and .styl suffixed files. The actual CSS remains unchanged. I don't know what workflow you use for npm release/publish but the script could for example run on some sort of pre-publish hook, and thus easily keep the Sass and Stylus outputs in sync with your CSS original for each new release.

  • 3

    Style on inputs being overwritten by destyle.css

    Hi! First of all thanks for this small package that I use systematically in all my projects :+1:

    I've just updated destyle.css today, and now all my inputs have their borders removed :sob:

    I've seen that you've changed the selector declaration for input 2 days ago, would it be the reason?

    In my browser, I can see that the destyle.css styles for input take precedence over my styles (which use classes):


    So of course, I'm complaining about the border, but there are also other properties that are overwritten (border is just the most visibly obvious).

  • 4

    [Question] scrollbar appearing on flex column header/footer/template when combining destyle w/ other CSS


    Here's a simple template containing :

    A scrollbar appears, but disappears when either removing the second stylesheet or adding line-height: normal to body.

    Any idea why ?


  • 5

    Reset padding and margin in universal selector

    While trying out destyle I found some left over paddings. They are small but still.

    • In the th and td elements


    (example page from destyle)

    • As well as in the option element


    (example page html5-kitchen-sink)

    I think it would be a good idea to reset the padding in the universal selector. This way no elements can be missed. Also margin could be reset like this as well, assuming its equally desired to be reset for all elements. This would also deduplicate quite a bit of code, as right now they are reset individually for every element.

    I'm happy to put up an PR if this is accepted.

  • 6

    Inherited border causes unexpected behaviors

    I noticed an issue with one style rule:

    textarea {
      border: inherit;

    Imagine using one of these elements within any container having a border. It will get inherited which makes no sense.

    I would recommend to set it to border: none or border: 0.

  • 7

    Line-height should be 1.5 to comply the WCAG guideline

    destyle's base line-height is 1.15 and this violates the WCAG Success Criterion 1.4.12: Text Spacing. To suits the criterion, line-height must be "at least 1.5 times the font size". So, html element's style should be: html { line-height: 1.5; /* 1 / -webkit-text-size-adjust: 100%; / 2 / -webkit-tap-highlight-color: transparent; / 3*/ }

  • 8

    fix: remove padding for td, th

    Fixes a left over padding for th and td elements.


    I was wondering, is there any reason for not resetting margin and padding in the universal selector for all elements? This would deduplicate a lot of code and prevent any other missed paddings and margins like this. I'd be happy to put up another PR and close this one. Just let me know.

    EDIT: Uh, I was just trying destyle out with html5-kitchen-sink and I found that option elements also have a padding... Might actually be a reason to move at least padding into the universal selector.


    Sorry, I should have put this in an issue instead. I was too optimistic that the td and th would be the only left over elements.

  • 9

    "dialog" tag reset

    I want to reset default dialog tag styles.

    For example, the following styles are the default for latest chrome.

      display: block;
      position: absolute;
      left: 0px;
      right: 0px;
      width: -webkit-fit-content;
      height: -webkit-fit-content;
      color: black;
      margin: auto;
      border-width: initial;
      border-style: solid;
      border-color: initial;
      border-image: initial;
      padding: 1em;
      background: white;

    I love this repository. Thank you.

  • 10

    Some elements maintain browser styles

    Nice work, however I encountered several issues if what I’m understanding you’re trying to do is right (by removing all styles added by the browser?):

    Using iPhone 7 Plus/iOS 12.1.2 on Mobile Safari, there are some elements that still have their default browser styles. Open your test page at https://nicolas-cusan.github.io/destyle.css/test.html and find the following elements by what’s contained in their content (viewing the source of the page is a challenge without my laptop):

    • Said no one, ever.
    • Definition List Title
    • Table Heading 1 (through 5)
    • Table Footer 1 (through 5)
    • Keyboard input: Cmd
    • Inline code: <div>code</div>
    • Sample output: This is sample output from a computer program.
    • Pre-formatted text P R E F O R M A T T E D T E X T ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
    • Strong is used to indicate strong importance.
    • This text has added emphasis.
    • The b element is stylistically different text from normal text, without any special importance.
    • The i element is text that is offset from the normal text.
    • The u element is text with an unarticulated, though explicitly rendered, non-textual annotation.
    • This text is deleted and This text is inserted.
    • This text has a strikethrough.
    • Superscript®.
    • Subscript for things like H2O.
    • This small text is small for for fine print, etc.
    • Abbreviation: HTML
    • This text is a short inline quotation.
    • This is a citation.
    • The dfn element indicates a definition.
    • The mark element indicates a highlight.
    • The variable element, such as x = y.
    • Canvas
    • Meter
    • Progress

    I admit many of these use bold, italics, underline, strikethroughs, etc, but if you’re trying to remove ALL browser defaults, those particular elements are not de-styled. Also, if I remember correctly, the canvas element has a default width and height added by the browser (similar to the iframe element) and doesn’t do much until you activate it with JavaScript.

    I hope these help. :)

  • 11


    • Remove IE support 🎉
    • Bring back outline for focusable elements
    • Remove redundant line-height: inherit rule from headings reset
    • Remove redundant text-decoration rule from abbr
    • Added svg selector to replaced content rule
    • Added text-transform: inherit rule to form elements
    • Replaced [disabled] selector with :disabled
    • Removed ::-moz-focus-inner rules for old Firefox versions
    • Improved :-moz-focusring style, no more dotted outline
    • Destyled select:disabled in Chrome
    • Add outline to focused [contenteditable] elements
    • Fixed border color inheritance for table borders in Chrome

    Closes #17 #16 #15 #14