Why do default buttons change color when borders are removed?

后端 未结 3 983
傲寒
傲寒 2021-01-13 14:15

As you can see from running the snippet below, the background color becomes darker when borders are removed. I guess it has something to do with background-color: butt

相关标签:
3条回答
  • 2021-01-13 14:55

    In Chrome, the user agent stylesheet styles <button>s as:

    button {
        -webkit-appearance: button;
        -webkit-writing-mode: horizontal-tb !important;
        text-rendering: auto;
        color: buttontext;
        letter-spacing: normal;
        word-spacing: normal;
        text-transform: none;
        text-indent: 0px;
        text-shadow: none;
        display: inline-block;
        text-align: center;
        align-items: flex-start;
        cursor: default;
        background-color: buttonface;
        box-sizing: border-box;
        margin: 0em;
        font: 400 13.3333px Arial;
        padding: 1px 6px;
        border-width: 2px;
        border-style: outset;
        border-color: buttonface;
        border-image: initial;
    }
    

    And border: none is a shorthand, which translates to:

    {
      border-top-color: initial;
      border-top-style: none;
      border-top-width: initial;
      border-right-color: initial;
      border-right-style: none;
      border-right-width: initial;
      border-bottom-color: initial;
      border-bottom-style: none;
      border-bottom-width: initial;
      border-left-color: initial;
      border-left-style: none;
      border-left-width: initial;
      border-image-source: initial;
      border-image-slice: initial;
      border-image-width: initial;
      border-image-outset: initial;
      border-image-repeat: initial;
    }
    

    The properties you are probably interested in are border-width, border-color and border-style (the apparently thin darker border comes from border-style: outset;).

    It is, indeed, quite strange how a border-style: outset; border-width: 2px button renders, when compared to one having a width of 1px or 3px:

    .\31 { border-width: 1px }
    .\33 { border-width: 3px }
    <button class="1">border-width: 1px;</button>
    <button class="2">border-width: 2px;</button>
    <button class="3">border-width: 3px;</button>

    It looks to me like Chrome is making an exception from how outset renders on buttons with a border-width of 2px, which happens to be the default border width set in user agent stylesheet.

    For a full explanation on what's going on, read comments, see @Mukyuu's answer which, IMHO, is correct, and see this fiddle - forked from the one in comments.


    Important: To be able to answer this type of CSS questions yourself, open Dev Console of Chrome (F12 or Ctrl/Cmd+I), select "Styles" side-tab:

    , click on the element you want to inspect in the DOM tree (on left) and find the shorthand property in the Styles list. In your case, border: none;. You'll notice a small arrow after the the property name:

    Click that arrow and you'll get the full list of what the browser parses it into.

    That's how I got the information provided in this answer and my answer is true now. If standards change over time, it might become obsolete but, if you do as outlined above, you'll always get the currently "correct" answer.

    0 讨论(0)
  • 2021-01-13 14:58

    I don't think you will find an explanation of this behavior in the classic CSS world because buttons are special elements. You may need to dig into how each browser implements the button element to understand what is happening.

    I don't have any official proof but to use easy words: buttons have default style applied by the browser (related to border and background) and if you try to alter any value you will break everything.

    Examples:

    <button style="background-color:grey">button</button>
    <button style="border-color:grey">button</button>
    <button style="border-width:3px">button</button>
    <button style="border-radius:5px">button</button>
    <button style="border-image:none">button</button>
    <button style="border-image-slice:1">button</button>
    <button style="background-origin:content-box">button</button>
    <button style="background-clip:content-box">button</button>
    <button>button</button>
    
     

    In the above, you will notice that all the buttons are losing their default style if we change any rule related to border or background (even irrelevant ones like border-image-slice or background-clip). In Firefox, it's different as the last four buttons will keep their default style. Don't know about the other browser but it's probably different too.

    UPDATE

    In the last version of Chrome the same thing seems to happen with input elements:

    <input>
    <input style="border-image-slice:1">
    <input style="border-image:none">
    <input style="border-width:3px">
    <input style="background-origin:content-box">

    0 讨论(0)
  • 2021-01-13 15:04

    It depends on how the browser handles buttons related


    The following was limited to the Chrome Browser:

    When you try to use all:initial to applies the initial (or default) value of a property to an element. You would at the very minimum need the following style to have the default button:

    -webkit-appearance: button;
    border-width: 2px;
    border-style: outset;
    border-color: buttonface;
    background-color: buttonface;
    

    Breaking down the button style:

    .noBorder {
      border: none;
    }
    
    .all-init {
      all: initial;
    }
    
    .leftover {
      color: buttontext;
      border-image: initial;
      font: 400 13.3333px Arial;
      padding: 1px 6px;
    }
    
    .p1 {
      /*property #1 required*/
      -webkit-appearance: button;
    }
    
    .p2 {
      /*property #2 required*/
      border-width: 2px;
    }
    
    .p3 {
      /*property #3 required*/
      border-style: outset;
    }
    
    .p4 {
      /*property #4 required*/
      border-color: buttonface;
    }
    
    .p5 {
      /* property #5 required*/
      background-color: buttonface;
    }
    
    .whole {
      -webkit-appearance: button;
      color: buttontext;
      background-color: buttonface;
      font: 400 13.3333px Arial;
      padding: 1px 6px;
      border-width: 2px;
      border-style: outset;
      border-color: buttonface;
      border-image: initial;
    }
    <button type="button" class="noBorder">No border</button> <br/>
    <button class="all-init">test0</button>
    <button class="all-init p1">test1</button>
    <button class="all-init p1 p2">test2</button>
    <button class="all-init p1 p2 p3">test3</button>
    <button class="all-init p1 p2 p3 p4">test4</button>
    <button class="all-init p1 p2 p3 leftover">test5a</button>
    <button class="all-init p1 p2 p4 leftover">test5b</button>
    <button class="all-init p1 p3 p4 leftover">test5c</button>
    <button class="all-init p2 p3 p4 leftover">test5d</button>
    <button class="all-init p1 p2 p3 p4 leftover">test6</button><br/>
    <button class="all-init p1 p2 p3 p4 p5">test7</button>
    <!-- test7 is the very minimum style required -->
    <button class="all-init p1 p2 p3 p4 leftover">test8a</button>
    <button class="all-init p1 p2 p3 p5 leftover">test8b</button>
    <button class="all-init p1 p2 p4 p5 leftover">test8c</button>
    <button class="all-init p1 p3 p4 p5 leftover">test8d</button>
    <button class="all-init p2 p3 p4 p5 leftover">test8e</button>
    <button class="all-init p1 p2 p3 p4 p5 leftover">test8f</button>
    <button class="all-init whole">test9</button>
    <br/><button>With border</button>

    Additional info: button was using ButtonFace which is CSS2 color name corresponding to HEX value: #F0F0F0 or RGB value: 240,240,240 to display it see more in http://www.iangraham.org/books/xhtml1/appd/update-23feb2000.html.


    Disclaimer: As Temani Afif said in this answer

    every browser have default style applied by the browser (related to border and background) and if you try to alter any value you will break everything.

    You could probably see test0 and test1 working in Edge and none working in Firefox since it was how the browser handles buttons related. You can see Andrei Gheorghiu answer for more detail for button complete style and debugging method.


    As such, the most common workaround that I've seen and implemented is not to use <button> but other elements such as <a> or <input> to support cross-browser.

    Example:

    .styling {
      background-color: #1cbcd8;
      color: #fff;
      border-color: #1cbcd8;
    }
    
    .styling:hover {
      background-color: #255FF9;
    }
    
    .extra {
      display: inline-block;
      cursor: default; /* or pointer */
      padding: 3px;
      text-decoration: none;
    }
    <input class="styling" type="submit" value="Test">
    
    <a href="#" class="styling extra">Test</a>

    0 讨论(0)
提交回复
热议问题