262

I tried this: http://jsfiddle.net/ilyaD/KGcC3/

HTML:

<select name="state" class="ddList">
    <option value="">(please select a state)</option>
    <option class="lt" value="--">none</option>
    <option class="lt" value="AL">Alabama</option>
    <option class="lt" value="AK">Alaska</option>
    <option class="lt" value="AZ">Arizona</option>
    <option class="lt" value="AR">Arkansas</option>
    <option class="lt" value="CA">California</option>
    <option class="lt" value="CO">Colorado</option>
</select>

CSS:

select { width: 400px; text-align: center; }
select .lt { text-align: center; }

As you can see, it doesn't work. Is there a CSS-only way to center text in the select-box?

David Refoua
  • 3,476
  • 3
  • 31
  • 55
ilyo
  • 35,851
  • 46
  • 106
  • 159

23 Answers23

480

There is a partial solution for Chrome:

select { width: 400px; text-align-last:center; }

It does center the selected option, but not the options inside the dropdown.

Julian Cardenas
  • 4,897
  • 2
  • 10
  • 10
99

That's for align right. Try it:

select{
    text-align-last:right;
    padding-right: 29px;
    direction: rtl;
}

the browser support for the text-align-last attribute can be found here: https://www.w3schools.com/cssref/css3_pr_text-align-last.asp It looks like only Safari is still not supporting it.

Community
  • 1
  • 1
Aly-Elgarhy
  • 1,169
  • 1
  • 10
  • 14
  • 10
    This should be the top answer, a simple & pure CSS solution that worked perfectly for me (although I changed `text-align-last: right;` to `center` as I wanted the labels in the middle). – JVG Jan 17 '17 at 06:47
  • This answer rocks! Nowhere else did I find such a simple solution. – udog Mar 29 '17 at 17:42
  • Thanks a lot, this answer should be the selected as this totally works! – Nick May 24 '17 at 06:44
  • 1
    text-align-last:center; alone works for me in chrome and firefox. not in edge and I would bet on safari neither. – Dennis Heiden Jun 19 '17 at 09:44
  • top notch answer – Moiz Aug 09 '18 at 00:59
  • 1
    This doesn't work in any mobile browsers. Which is where primarily I would like it to work. – evolross Nov 20 '18 at 22:36
  • 2
    To be clear for those finding this answer, this gives a centered-ish effect if your options are similarly sized, but it's not actually centering things, just aligning them right and adding padding. In my case, I have options ranging from 1 - 5 characters, so it looks very odd to have them all aligned right, because the spacing is not even between the left & right side. – bjg222 Sep 27 '19 at 18:47
  • @bjg222 please take a look at the first comment (by @JVG) that may help with your specific case. Also, my answer above (the most voted) suggests `center` instead of `right` – Julian Cardenas Jun 09 '22 at 21:06
67

Yes, it is possible. You can use text-align-last

text-align-last: center;
Manjeet Kumar Nai
  • 1,382
  • 1
  • 13
  • 16
  • 4
    This seems to center the value displayed in the select when closed. The options in the dropdown are still aligned to the left (at least in Chrome as of Sep 2019) – bjg222 Sep 27 '19 at 18:39
  • 1
    Yes I want to display in the center and it's correct – Pritesh Oct 01 '19 at 05:16
65

2020, Im using:

select {
    text-align: center;
    text-align-last: center;
    -moz-text-align-last: center;
}
jzuhri
  • 812
  • 7
  • 8
63

You have to put the CSS rule into the select class.

Use CSS text-indent

Example

<select class="day"> /* option 1 option 2 option 3 option 4 option 5 here */ </select>

CSS code

select { text-indent: 5px; }
Brian Webster
  • 30,033
  • 48
  • 152
  • 225
marc carreras
  • 709
  • 5
  • 5
  • 3
    Either I didn't get it, or it simply does not work for aligning the text – matanster May 25 '16 at 10:55
  • text-indent... Interesting, I didn't know about that property. Thanks a lot! – Froxx Jul 07 '16 at 14:39
  • 11
    This will only work for one specific option, text-indent depends on how much horizontal space takes the text of the option in relation to the selectbox width, so this is an incomplete answer, i'm amazed it got 43 upvotes, the proper answer using text indent was provided by Mr Smee above. – Lu Roman Sep 28 '16 at 03:13
  • An interesting idea, but it won't work with a percentage so how can you center every single item? – GeorgeButter Nov 07 '16 at 00:05
  • This is the correct answer. Using text-indent: 50% will center the option for you inside the select. – Giga Chad Coding May 01 '18 at 18:15
  • Indentation is not the same as centering. – showdev Jul 13 '21 at 22:43
35

I'm afraid this isn't possible with plain CSS, and won't be possible to make completely cross-browser compatible.

However, using a jQuery plugin, you could style the dropdown:

https://www.filamentgroup.com/lab/jquery-ui-selectmenu-an-aria-accessible-plugin-for-styling-a-html-select.html

This plugin hides the select element, and creates span elements etc on the fly to display a custom drop down list style. I'm quite confident you'd be able to change the styles on the spans etc to center align the items.

Adrian
  • 2,233
  • 1
  • 22
  • 33
Curtis
  • 101,612
  • 66
  • 270
  • 352
  • 1
    http://web.archive.org/web/20160328192510/http://filamentgroup.com/lab/jquery-ui-selectmenu-an-aria-accessible-plugin-for-styling-a-html-select.html Here is the improved version now that filamentgroup's is no longer maintained. https://github.com/fnagel/jquery-ui – cdignam Aug 16 '17 at 15:43
22

just using this:

select {

text-align-last: center;
padding-right: 29px;

}
Gerry
  • 10,337
  • 3
  • 31
  • 40
Aouidane Med Amine
  • 1,571
  • 16
  • 17
  • 4
    You do not need to include "padding-right: 29px;" if you are using "center". I suspect you have because you copied Aly-Elgarhy's answer from Oct 25 '16. – Jayden Lawson May 05 '18 at 07:34
  • 1
    When you copy from someone's answer you should mention their names. – Munim Munna Jul 24 '18 at 16:05
  • Nop , i copied that directely from my Code as it is , that's why i puted the padding-right , may be i copied the solution from another one into my code , and then i copied the solution from my code into stackoverflow. – Aouidane Med Amine Jan 08 '19 at 10:59
21

select {
  text-align: center;
  text-align-last: center;
}
option {
  text-align: left;
}
<select>
   <option value="">(please select a state)</option>
   <option class="lt" value="--">none</option>
   <option class="lt" value="AL">Alabama</option>
   <option class="lt" value="AK">Alaska</option>
   <option class="lt" value="AZ">Arizona</option>
   <option class="lt" value="AR">Arkansas</option>
   <option class="lt" value="CA">California</option>
   <option class="lt" value="CO">Colorado</option>
</select>
Jamie Hutber
  • 26,790
  • 46
  • 179
  • 291
17

This JS function should work for you

function getTextWidth(txt) {
  var $elm = $('<span class="tempforSize">'+txt+'</span>').prependTo("body");
  var elmWidth = $elm.width();
  $elm.remove();
  return elmWidth;
}
function centerSelect($elm) {
    var optionWidth = getTextWidth($elm.children(":selected").html())
    var emptySpace =   $elm.width()- optionWidth;
    $elm.css("text-indent", (emptySpace/2) - 10);// -10 for some browers to remove the right toggle control width
}
// on start 
$('.centerSelect').each(function(){
  centerSelect($(this));
});
// on change
$('.centerSelect').on('change', function(){
  centerSelect($(this));
});

Full Codepen here: http://codepen.io/anon/pen/NxyovL

Mr. Smee
  • 968
  • 11
  • 28
9

I have always gotten away with the following hack to get it to work with css only.

padding-left: 45%;
font-size: 50px;

padding will center the text and can be tweaked for the text size :)

This is obviously not 100% correct from a validation point of view I guess but it does the job :)

Ben Pretorius
  • 4,079
  • 4
  • 34
  • 28
7

Alternative "fake" solution if you have a list with options similar in text length (page select for example):

padding-left: calc(50% - 1em);

This works in Chrome, Firefox and Edge. The trick is here to push the text from the left to the center, then substract the half of length in px, em or whatever of the option text.

enter image description here

Best solution IMO (in 2017) is still replacing the select via JS and build your own fake select-box with divs or whatever and bind click events on it for cross-browser support.

Dennis Heiden
  • 757
  • 8
  • 16
6

try this :

select {
    padding-left: 50% !important;
    width: 100%;
}
hmahdavi
  • 2,250
  • 3
  • 38
  • 90
  • as of October 2020, this solution works on Chrome, Safari, and Brave. (I didn't test in other browsers). Thanks a lot hmahdavi – Alfrex92 Oct 15 '20 at 09:33
5

Not quite Centering but using example above you can make a left margin in select box.

<style>.UName { text-indent: 5px; }</style><br>

<select  name="UserName" id="UserName" size="1">
    <option class="UName" selected value="select">Select User</option>
    <option class="UName" value="User1">User 1 Name</option>
    <option class="UName" value="User2">User 2 Name </option>
    <option class="UName" value="User3">User 3 Name</option>
</select>
Richard
  • 51
  • 1
  • 3
5

this worked for me:

text-align: center;
text-align-last: center;
2

You can't really customise <select> or <option> much. The only way (cross-browser) would be to manually create a drop down with divs and css/js to create something similar.

Emmanuel
  • 4,933
  • 5
  • 46
  • 71
2

If you didn't find any solution, you can use this trick on angularjs or using js to map selected value with a text on the div, this solution is full css compliant on angular but need a mapping between select and div:

var myApp = angular.module('myApp', []);

myApp.controller('selectCtrl', ['$scope',
  function($scope) {
    $scope.value = '';


  }
]);
.ghostSelect {
  opacity: 0.1;
  /* Should be 0 to avoid the select visibility but not visibility:hidden*/
  display: block;
  width: 200px;
  position: absolute;
}
.select {
  border: 1px solid black;
  height: 20px;
  width: 200px;
  text-align: center;
  border-radius: 5px;
  display: block;
}
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example - example-guide-concepts-1-production</title>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="myApp">
  <div ng-app ng-controller="selectCtrl">
    <div class=select>
      <select ng-model="value" class="ghostSelect">
        <option value="Option 1">Option 1</option>
        <option value="Option 2">Option 2</option>
        <option value="Option 3">Option 3</option>
      </select>
      <div>{{value}}
      </div>
    </div>
  </div>
</body>

Hope this could be useful for someone as it took me one day to find this solution on phonegap.

jup31
  • 53
  • 8
1

While you cannot center the option text within a select, you can lay an absolutely positioned div over the top of the select to the same effect:

#centered
{
  position: absolute;
  top: 10px;
  left: 10px;
  width: 818px;
  height: 37px;
  text-align: center;
  font: bold 24pt calibri;
  background-color: white;
  z-index: 100;
}

#selectToCenter
{
  position: absolute;
  top: 10px;
  left: 10px;
  width: 840px;
  height: 40px;
  font: bold 24pt calibri;
}

$('#selectToCenter').on('change', function () {
    $('#centered').text($(this).find('option:selected').text());
});

<select id="selectToCenter"></select>
<div id="centered"></div>

Make sure the both the div and select have fixed positions in the document.

szozz
  • 145
  • 1
  • 6
1

On your select use width: auto and no padding to see how long your text is. I'm using 100% available width on my select and all of my options have the same length, this allows me to use very simple css.

text-indent will move the text from left, similar to padding-left
120px is my text length - I want to center it so take half of that size and half of the select size, leaving me with 50% - 60px

select{
  width: 100%;
  text-indent: calc(50% - 60px);
}

What if I have different sizes of options?

It is possible, however, the solution will not be a pretty one.
The former solution might get you really close to being centered if the difference between options isn't like 5 characters.

If you still need to center it more precisely you can do this

Prepare this class:

.realWidth{
   width: auto;
}

Apply onChange listener to select element

In that listener apply .realWidth to the select element with

const selectRef = document.getElementById("yourId");
selectRef.classList.add("realWidth");

Get access to the real width of the option.

const widthOfSelect = selectRef.getBoundingClientRect().width / 2;

widthOfSelect is the width you are looking for. Store it in global/component variable.

Remove the realWidth, you don't need it anymore.

selectRef.classList.remove("realWidth");

I am using react, I'm not sure this will work in vanilla, if not you have to find another solution.

<select style={`textIndent: calc(50% - ${widthOfSelect}) %`}> ... </select>

Another solution, however, that is a bad one could be creating the CSS classes with js and putting it to head.

PROS:

  1. probably works, I haven't tried the dynamic solution but it should work.

CONS:

  1. if the program is not fast enough user will see the width: auto taking place and thus wonder what's going on. If that is the case just create duplicate select, hide it behind something with a higher z-index and apply the on select listener from the original to the hidden duplicate.
  2. Might be hard to use if you cant inline the style because of vanilla limitation, but you can make a script to optimize the appendChild to the head.
Lukáš Brýla
  • 680
  • 6
  • 6
0

I ran into this issue where a client was insisting on this, and they were on a Mac and and iPhone.

I wound up using media queries and a percentage padding for padding-left. Was this a satisfying solution? Not at all, but it let me move on.

redcartel
  • 292
  • 1
  • 3
  • 15
0

Easiest way: Use padding-left

select{
   padding-left:2rem
}
Tanishka Bansal
  • 49
  • 1
  • 10
0

I had a similar problem. My work-around was to change to a fixed size font in the style section:

option {
  font-family: Courier New;
  width: 12ch;
  font-size: 14pt
}

select {
  font-family: Courier New;
  width: 14ch;
  font-size: 14pt
}

In body I padded the shown options with underlines to make them the same length.
Note used underlines on both sides to center display:

<select onchange='O.src=this.options[this.selectedIndex].value' align="center">
  <option value="" align="center">___(none)___</option>
  <option value="https://www.247backgammon.org/" align="center">_Backgammon_</option>
  <option value="https://www.247klondike.com/klondikeSolitaire3card.php" align="center">__Klondike__</option>
  <option value="https://www.247minesweeper.com/" align="center">_Minesweeper</option>
  <option value="https://sudoku.com/" align="center">
    <p>___Soduku___</p>
  </option>
</select>
Zach Jensz
  • 3,650
  • 5
  • 15
  • 30
-1

It's not 100% yet, but you can use this snippet!

text-align-last: center; // For Chrome text-align: center; // For Firefox

Doesn't work on Safari or Edge, for now!

alvescleiton
  • 1,063
  • 11
  • 8
-3

if the options are static, you could listen for the change event on your select box and add padding for each individual item

$('#id').change(function() {
    var select = $('#id');
    var val = $(this).val();

    switch(val) {
        case 'ValOne':
            select.css('padding-left', '30px');
            break;
        case 'ValTwoLonger':
            select.css('padding-left', '20px');
             break;
        default:
            return;
    }
});
  • It's not a good ideia putting padding-left for each word. How about this words comming from de database and are dynamic? – alvescleiton Jun 15 '20 at 12:31