Here are two questions, but the second follows from the first.

Why do select and input different heights?

 * { box-sizing: border-box; } select, input[type="text"] { padding: 2px; border: 1px solid #ccc; font-size: 13px; } 
 <select> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> <input type="text" value="Test" /> 

And how to fix it so that it is flexible?

Nuances

I try to set the same height for select and input , but I really want to do it flexibly, which means that I don’t want to just set a fixed height. So that I can easily change font-size without having to change the height. And I don’t quite understand why they have different heights due to the fact that they have the same font size and the same padding , border and box-sizing .

I also understand that you can choose different padding for input and select , but I want to understand the mechanics and causes of these results, as well as solve them "without hacks."

Of the browsers, Chrome is most curious, but the cross-browser solution will be generally perfect.

    3 answers 3

    It is not in all browsers. Different heights is one of the features of styling a particular browser.

    In select for select have the same height, you need to remove the arrow on the right from it. But here is a nuance: if we add an arrow to the text field, it will not change its height. so it’s not 100% true that this is because of the arrow, but this is one of the solutions.

    For this case, you can apply 3 solutions:

    Option 1:

    Adding a background image instead of a standard arrow

     * { box-sizing: border-box; } select, input[type="text"] { width: auto; padding: 2px; border: 1px solid #ccc; font-size: 13px; -webkit-appearance: none; } select { padding-right: 10px; background-image: url(http://s1.iconbird.com/ico/2013/8/426/w32h321377581133134TriangleDown.png); background-size: 16%; background-repeat: no-repeat; background-position-y: center; background-position-x: calc(100% - 5px); } 
     <select> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> <input type="text" /> 

    Option 2:

    select'а frame in div and add pseudo- select'а :after

    Based on the answer from eng stackoverflow : css-change-dropdown-arrow-to-unicode-triangle

     * { box-sizing: border-box; } select, input[type="text"] { padding: 2px; border: 1px solid #ccc; font-size: 13px; -webkit-appearance: none; } select {padding-right: 10px;} .select {display: inline-block; position: relative;} .select:after { display: block; position: absolute; right: 5px; content: 'â–Ľ'; font-size: 0.6rem; top: 50%; pointer-events: none; transform: translateY(-50%); } 
     <div class="select"> <select> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> </div> <input type="text" value="Test" /> 

    Option 3:

    This option is similar to Option 2 , but here we are instead :after using svg

     * { box-sizing: border-box; } select, input[type="text"] { padding: 2px; border: 1px solid #ccc; font-size: 13px; -webkit-appearance: none; } select {padding-right: 10px;} .select {display: inline-block; position: relative;} .select svg { display: block; position: absolute; right: 5px; width:20px;height:20px; font-size: 0.6rem; top: 50%; pointer-events: none; transform: translateY(-50%); } 
     <div class="select"> <select> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> <svg width="15" height="15" viewBox="0 0 15 15"> <path d="M 8,5.5 11,9.5 14,5.5 z"></path> </svg> </div> <input type="text" value="Test" /> 

    These methods will also solve the problem that select rendered differently in different browsers and operating systems.

    • one
      I really do not want to remove the arrow from select . - Vadim Ovchinnikov

    If you look closely, then in standard styles the input for the border has the values border-style: inset and border-width: 2px . Therefore, by changing the width of the input path by 1 pixel, we interfere with the size of its box. To avoid this, you can make the border single-pixel and transparent, and simulate its appearance for input with the help of box-shadow .

     * { box-sizing: border-box; } select, input[type="text"] { padding: 2px; font-size: 13px; border: 1px solid #ccc; } input[type="text"] { border-color: transparent; box-shadow: 0px 0px 0 1px #ccc; } 
     <select> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> </select> <input type="text" value="Test" /> 

      Try it like this

       select, input[type="text"] { padding: 2px; border: 1px solid #ccc; font-size: 13px; min-height: 23px; } 
      • one
        See it. Even if we close our eyes to the fact that nothing here is told about the reasons (which are also interesting to me), it will not work here, if you set the font-size another one, say 15px . And my answer says about flexibility. And where did you get the number 23px ? Why not 22 or 24? - Vadim Ovchinnikov
      • one
        By the way, you can simply set the height or play with padding , but I just want to change the font-size to get the same height select and input . - Vadim Ovchinnikov