syrkull
syrkull

Reputation: 2344

text-align is not working on safari <select>

I have tried aligning the text in the <select> element to the right or the center in safari. But nothing worked. text-align:center; worked in all browsers except safari. direction:rtl; and dir="rtl" did not do anything. the list is always align to the left in Safari. -webkit-appearance: none; does not help either. Please I need a solution.

Upvotes: 31

Views: 50439

Answers (9)

Ali Ankarali
Ali Ankarali

Reputation: 3127

text-align-last works as of writing this in Aug. 2023. both on Mac and iPhone Safari.

select {
  text-align-last: center;
}

Upvotes: 19

BritishSam
BritishSam

Reputation: 1090

Vanilla js method is to use a normal input to display the selected text of a hidden select box, then you can style the input how you want to look like a select box.

const inputs = document.getElementsByClassName('js-fake-input');
const selects = document.getElementsByClassName('js-select');

for (let i = 0; i < inputs.length; i++) {
  getSelected(i);
  selects[i].addEventListener("change", function() {
    getSelected(i);
  });
}

function getSelected(index){
  inputs[index].value = selects[index].options[selects[index].selectedIndex].text;
}
.select-holder{
  position: relative;
  width:200px;
  margin-bottom: 10px;
}

.select-holder select{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  opacity: 0 ;
}

.select-holder input{
  text-align: center;
  width:100%
}
<div class="select-holder">
  <select class="js-select">
    <option>
      Option 1
    </option>
    <option>
      Option 2
    </option>
  </select>
  <input type="text" class="js-fake-input">
</div>
<div class="select-holder">
  <select class="js-select">
    <option>
      Option 1
    </option>
    <option selected>
      Option 2
    </option>
  </select>
  <input type="text" class="js-fake-input">
</div>
<div class="select-holder">
  <select class="js-select">
    <option>
      Option 1
    </option>
    <option>
      Option 2
    </option>
  </select>
  <input type="text" class="js-fake-input">
</div>

Upvotes: 1

Petro Pavliuk
Petro Pavliuk

Reputation: 443

For me text-align: -weblit-center is not working on mobile Safari. I found this solution text-indent: 5px hanging; (change 5px for your situation). This property is working only on safari.

Upvotes: 2

Oleg Karasik
Oleg Karasik

Reputation: 969

I have faced a very similar issue. My problem was to align text inside <select> element based on text-align style. This was required to correctly handle media based styles.

In Chrome I was using text-align-last style, however in Safari this style isn't supported (according to MDN).

That is why I came up with the following JavaScript function (using text-indent) which does left and right text alignment (not center as it OP question, but in my defense I think this code can be modified to properly calculate text-indent for centering):

function SELECT_applyTextAlign(element) {
  let styles = document.defaultView.getComputedStyle(element, "");
  if (    styles.textAlign == 'left' 
      || (styles.direction === 'ltr' && styles.textAlign === 'start')) {
    // Left alignment doesn't require any kind of calculations.

    element.style.textIndent = 0;
    return;
  }
  if (    styles.textAlign == 'right' 
      || (styles.direction === 'ltr' && styles.textAlign === 'end')) {
    // Right alignment requires a proper width calculations.

    let option = element.querySelector('option[value=\'' + element.value + '\']');
    if (!option) {
      return;
    }

    // Get original element width
    let width = element.getBoundingClientRect().width;

    // Create temporary <select> and <option> elements
    let sz_select = document.createElement('select');
    let sz_option = document.createElement('option');

    // This should ensure both <select> have the same styles and <option> have the same text
    sz_select.style.cssText = styles.cssText;
    sz_select.style.width = 'auto';

    sz_select.value = option.value;

    sz_option.value = option.value;
    sz_option.text = option.text;

    // Append <option>
    sz_select.appendChild(sz_option);

    // Append <select>
    element.parentNode.insertBefore(sz_select, element.nextSibling);

    // Copy calculated width
    let sz_width = sz_select.getBoundingClientRect().width;

    element.style.textIndent = (width - sz_width) + 'px'

    // Remove unnecessary element
    sz_select.remove();
  }
}

Then I have attached load and resize event handlers to ensure all <select> elements are processed when page is loaded and when windows size is changed:

window.addEventListener('load', function() {
  let selects = document.getElementsByTagName('select');
  Array.prototype.filter.call(selects, function(element) {
    SELECT_applyTextAlign(element);

    element.addEventListener('change', function () {
      SELECT_applyTextAlign(element);
    }, false);
  });
}, false);

window.addEventListener('resize', function () {
  let selects = document.getElementsByTagName('select');
  Array.prototype.filter.call(selects, function(element) {
    SELECT_applyTextAlign(element);
  });
}, false);

Hope this could help someone (tested in chrome, iOS and safari)

Upvotes: 1

Doug
Doug

Reputation: 685

Is a bug in safari.

Bug 40216 - text-align doesn't work on select tags
https://bugs.webkit.org/show_bug.cgi?id=40216

Filed 2010 😢

Upvotes: 4

Marcelo Dornelas
Marcelo Dornelas

Reputation: 17

This worked for me.

select {
    text-align:-moz-center;
    text-align:-webkit-center;
}

Upvotes: -3

jup31
jup31

Reputation: 53

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.

Upvotes: 1

Trey
Trey

Reputation: 5520

As I said in my comment above I know this isn't actually a css solution, but if it's important to you this works as a work around if you're willing to use jquery.... it does NOT work in chrome correctly, but if you check for the browser you could just load it for safari:

http://jsfiddle.net/nEGV4/4/

Upvotes: 0

Anirudh Ramanathan
Anirudh Ramanathan

Reputation: 46788

For Safari

text-align: -webkit-center;

However, the best way to analyze the working of HTML/CSS is the Web-Inspector in Safari.

enter image description here More >>

Upvotes: 1

Related Questions