Text Stroke (-webkit-text-stroke) css Problem - css

I am working on a personal project with NextJs and TailwindCSS.
upon finishing the project I used a private navigator to see my progress, but it seems that the stroke is not working as it should, I encounter this in all browsers except Chrome.
Here is what i get :
Here is the desired behavior :
Code:
<div className="outline-title text-white pb-2 text-5xl font-bold text-center mb-12 mt-8">
Values & Process
</div>
Css:
.outline-title {
color: rgba(0, 0, 0, 0);
-webkit-text-stroke: 2px black;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
Can someone explain or help to fix this.
Browser compatibility:

TL;DR: -webkit-text-stroke is still quite unpredictable
the text-shadow as proposed by #Satheesh Kumar is probably the most reliable solution.
#Luke Taylor's approach – duplicating text to a background pseudo element – also provides a good workaround.
Anatomy of a variable font
As #diopside: pointed out this rendering behaviour is related to variable fonts.
The reason for these inner outlines is based on the structure of some variable fonts.
'Traditional' fonts (so before variable fonts) – only contained an outline shape and maybe a counter shape e.g the cut out inner 'hole' of a lowercase e glyph.
Otherwise you would have encountered undesired even/odd issues resulting in excluded shapes caused by overlapping path areas.
Applying this construction method, you will never see any overlap of shapes. You could imagine them as rather 'merged down' compound paths. Counter shapes like the aforementioned hole were based on simple rules like a counterclockwise path directions – btw. you might still encounter this concept in svg-clipping paths - not perfectly rendering in some browsers).
Variable fonts however allow a segemented/overlapping construction of glyphs/characters to facilitate the interpolation between different font weights and widths.
Obviously webkit-text-stroke outlines the exact bézier anatomy of a glyph/character resulting in undesired outlines for every glyph component.
This is not per se an issue of variable fonts, since weight and width interpolations has been used in type design for at least 25 years. So this quirky rendering issue depends on the used font – a lot of classic/older fonts compiled to the newer variable font format will still rely on the old school aproach (avoiding any overlap).
Other issues with -webkit-text-stroke
Inconsistent rendering:Firefox renders the stroke with rounded corners
weird "kinks and tips" on sharp angles
Firefox - Roboto Flex(variable font); 2. Chromium - Roboto Flex(variable font); 3. Chromium - Roboto (static font);
Example snippet: test -webkit-text-stroke rendering
addOutlineTextData();
function addOutlineTextData() {
let textOutline = document.querySelectorAll(".textOutlined");
textOutline.forEach((text) => {
text.dataset.content = text.textContent;
});
}
let root = document.querySelector(':root');
sampleText.addEventListener("input", (e) => {
let sampleText = e.currentTarget.textContent;
let textOutline = document.querySelectorAll(".textOutlined");
textOutline.forEach((text) => {
text.textContent = sampleText;
text.dataset.content = sampleText;
});
});
strokeWidth.addEventListener("input", (e) => {
let width = +e.currentTarget.value;
strokeWidthVal.textContent = width + 'em'
root.style.setProperty("--strokeWidth", width + "em");
});
fontWeight.addEventListener("input", (e) => {
let weight = +e.currentTarget.value;
fontWeightVal.textContent = weight;
document.body.style.fontWeight = weight;
});
useStatic.addEventListener("input", (e) => {
let useNonVF = useStatic.checked ? true : false;
if (useNonVF) {
document.body.style.fontFamily = 'Roboto';
} else {
document.body.style.fontFamily = 'Roboto Flex';
}
});
#font-face {
font-family: 'Roboto Flex';
font-style: normal;
font-weight: 100 1000;
font-stretch: 0% 200%;
src: url(https://fonts.gstatic.com/s/robotoflex/v9/NaNeepOXO_NexZs0b5QrzlOHb8wCikXpYqmZsWI-__OGfttPZktqc2VdZ80KvCLZaPcSBZtOx2MifRuWR28sPJtUMbsFEK6cRrleUx9Xgbm3WLHa_F4Ep4Fm0PN19Ik5Dntczx0wZGzhPlL1YNMYKbv9_1IQXOw7AiUJVXpRJ6cXW4O8TNGoXjC79QRyaLshNDUf9-EmFw.woff2) format('woff2');
}
body {
font-family: 'Roboto Flex';
font-weight: 500;
margin: 2em;
}
.p,
p {
margin: 0;
font-size: 10vw;
}
.label {
font-weight: 500!important;
font-size: 15px;
}
.resize {
resize: both;
border: 1px solid #ccc;
overflow: auto;
padding: 1em;
width: 40%;
}
:root {
--textOutline: #000;
--strokeWidth: 0.1em;
}
.stroke {
-webkit-text-stroke: var(--strokeWidth) var(--textOutline);
color: #fff
}
.textOutlined {
position: relative;
color: #fff;
}
.textOutlined:before {
content: attr(data-content);
position: absolute;
z-index: -1;
color: #fff;
top: 0;
left: 0;
-webkit-text-stroke: var(--strokeWidth) var(--textOutline);
display: block;
width: 100%;
}
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght#100;300;400;500;700;900" rel="stylesheet">
<p class="label">stroke width<input id="strokeWidth" type="range" value="0.3" min='0.01' max="0.5" step="0.001"><span id="strokeWidthVal">0.25em</span> | font-weight<input id="fontWeight" type="range" value="100" min='100' max="900" step="10"><span id="fontWeightVal">100</span>
<label><input id="useStatic" type="checkbox">Use static Roboto</label><br><br>
</p>
<div id="sampleText" class="stroke p" contenteditable>AVATAR last <br>Airbender</div>
<p class="label">Outline via pseudo element in background</p>
<div class="resize">
<p class="textOutlined">AVATAR last Airbender
</p>
</div>
However, these rendering issues are rare as long as your stroke-width is not significantly larger than ~0.1em (or 10% of your current font-size).
See also "Outline effect to text"

Due to browser compatibility -webkit-text-stroke will not support in a few browsers. You can achieve the outline effect by using shadow.
Hope this works!
.outline-title {
font-family: sans-serif;
color: white;
text-shadow:
1px 1px 0 #000,
-1px -1px 0 #000,
1px -1px 0 #000,
-1px 1px 0 #000,
1px 1px 0 #000;
font-size: 50px;
}
<div class="outline-title text-white pb-2 text-5xl font-bold text-center mb-12 mt-8">
Values & Process
</div>
---- UPDATE ---

Its a known issue when using variable-width fonts in certain browsers. As to the why, I have no idea
https://github.com/rsms/inter/issues/292#issuecomment-674993644

One approach you can take is to cover over the internal lines with a second copy of the text. This produces pretty good results:
Using pseudo-elements, you could do this even without adding a second element to your HTML:
.broken {
-webkit-text-stroke: 2px black;
}
.fixed {
position: relative;
/* We need double the stroke width because half of it gets covered up */
-webkit-text-stroke: 4px black;
}
/* Place a second copy of the same text over top of the first */
.fixed::after {
content: attr(data-text);
position: absolute;
left: 0;
-webkit-text-stroke: 0;
pointer-events: none;
}
div { font-family: 'Inter var'; color: white; }
/* (optional) adjustments to make the two approaches produce more similar shapes */
.broken { font-weight: 800; font-size: 40px; }
.fixed { font-weight: 600; font-size: 39px; letter-spacing: 1.2px; }
<link href="https://rsms.me/inter/inter.css" rel="stylesheet">
Before:
<div class="broken">
Values & Process
</div>
After:
<div class="fixed" data-text="Values & Process">
Values & Process
</div>
Note, however, that using a second element is likely better for accessibility than using a pseudo-element, since you can mark it with aria-hidden and ensure screen readers won’t announce the text twice.
A complete example:
.broken {
-webkit-text-stroke: 2px black;
}
.fixed {
position: relative;
/* We need double the stroke width because half of it gets covered up */
-webkit-text-stroke: 4px black;
}
/* Place the second copy of the text over top of the first */
.fixed span {
position: absolute;
left: 0;
-webkit-text-stroke: 0;
pointer-events: none;
}
div { font-family: 'Inter var'; color: white; }
/* (optional) adjustments to make the two approaches produce more similar shapes */
.broken { font-weight: 800; font-size: 40px; }
.fixed { font-weight: 600; font-size: 39px; letter-spacing: 1.2px; }
<link href="https://rsms.me/inter/inter.css" rel="stylesheet">
Before:
<div class="broken">
Values & Process
</div>
After:
<div class="fixed">
Values & Process
<span aria-hidden="true">Values & Process</span>
</div>

I had the same problem before,
It turns out that I've initialized 'Montserrat' as my primary font and applied
Some other font to an element.
But when I changed the font from 'Montserrat' to 'Poppins' the problem was solved :P

Related

Why does the Internal style sheet works and External style sheet don't?

I am helping to create a website, we are two people working on this project. The other person is responsible for the visual part (CSS, html and javascript), I'm responsible for the internal functioning of the website (php, javascript and database, ...).
I created a code for the site pop up error messages.
I used some css to create the pop up mensage and i't work when I use the internal style sheet.
The problem it's when I use external style sheet, the pop up effect it's not working.
I did some research and find that this could be caused by encoding the css.
So to solve this problem I'm doing this:
In my mystyle.css:
#charset "utf-8";
In my head.php:
<meta charset="utf-8">
But this did not solve my problem.
I did some more research and there is the possibility of being caused by fetching the external css in the wrong place.
I think it's not caused by this because the other person's css are working. I'm saving my css in the same folder as the other person is saving hers. I call the css files the same as the other person.
My head.php:
<link rel="stylesheet" href="<?php echo $base_url;?>/css/bootstrap.css">
<link rel="stylesheet" href="<?php echo $base_url;?>/css/mystyle.css">
What could be causing this, or am I doing something wrong?
My full code for external style sheet.
mystyle.css:
#charset "utf-8";
.modal-error-box {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding: 200px 0px 100px 0px;
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
/* The Close Button */
.close{
color: black;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
.modal-error-box-header{
margin: auto;
width: 35%;
height: 5%;
border: 3px solid black;
background-color: Red;
color: Black;
}
.modal-error-box-body
{
margin: auto;
width: 35%;
height: 20%;
border: 3px solid black;
text-align: center;
background-color: white;
color: Black;
overflow: scroll;
}
html:
<div id="erro-gravar-operacoes" class = "modal-error-box">
<div id ="error-gravar-header1" class = "modal-error-box-header">
Mensagem de ERRO:
<span id="close-erro1" class="close">×</span>
</div>
<div id = "erro-gravar-body1" class="modal-error-box-body">
</div>
</div>
javascript:
function validatesubmitform(id_var)
{
//validate form.
if(validate == false){
var div_error = document.createElement("p");
div_error.setAttribute('id', "id_element_erro" );
if(text_erro!="")
{
var element_erro = document.createElement("p");
element_erro.setAttribute('id', "id_element_erro1" );
var texto_erro = document.createTextNode(text_erro);
element_erro.appendChild(texto_erro);
div_error.appendChild(element_erro);
}
if(text_erro1!="")
{
var element_erro1 = document.createElement("p");
element_erro1.setAttribute('id', "id_element_erro2" );
var texto_erro1 = document.createTextNode(text_erro1);
element_erro1.appendChild(texto_erro1);
div_error.appendChild(element_erro1);
}
var div_display = document.getElementById("erro-altera-body2");
div_display.appendChild(div_error);
document.getElementById("erro-altera-operacoes").style.display='block';
}
return validate;
}
Help with this problem is really necessary, and greatly appreciated.
Thanks in advance for future contributions to solving this problem.
One way to do this is by giving yourself write permission in the css folder
Ubuntu: sudo chown -R username /.../.../.../.../css
If everything seems to be fine and some files don't load, check the file permissions.

How indicate 'open end' for a DIV box with CSS

I am using vis.js to display some items on a timeline.
Some items have a clear start and end date which allows me to simply use the vis.js timeline features.
By default a div box is drawn which I can overwrite with my custom CSS.
This is a running example how this looks like with some ugly custom styling:
// DOM element where the Timeline will be attached
var container = document.getElementById('visualization');
// Create a DataSet (allows two way data-binding)
var items = new vis.DataSet([
{id: 1, content: 'item 1', start: '2014-04-16', end: '2014-04-19'},
]);
// Configuration for the Timeline
var options = {};
// Create a Timeline
var timeline = new vis.Timeline(container, items, options);
body {
font-family: purisa, 'comic sans', cursive;
}
.vis-timeline {
border: 2px solid purple;
font-family: purisa, 'comic sans', cursive;
font-size: 12pt;
background: #ffecea;
}
.vis-item {
border-color: #F991A3;
background-color: pink;
font-size: 15pt;
color: purple;
box-shadow: 5px 5px 20px rgba(128,128,128, 0.5);
}
.vis-item,
.vis-item.vis-line {
border-width: 3px;
}
.vis-item.vis-dot {
border-width: 10px;
border-radius: 10px;
}
.vis-item.vis-selected {
border-color: green;
background-color: lightgreen;
}
.vis-time-axis .vis-text {
color: purple;
padding-top: 10px;
padding-left: 10px;
}
.vis-time-axis .vis-text.vis-major {
font-weight: bold;
}
.vis-time-axis .vis-grid.vis-minor {
border-width: 2px;
border-color: pink;
}
.vis-time-axis .vis-grid.vis-major {
border-width: 2px;
border-color: #F991A3;
}
<link href="http://visjs.org/dist/vis.css" rel="stylesheet"/>
<script src="http://visjs.org/dist/vis.js"></script>
<div id="visualization"></div>
</body>
</html>
This is basically creating a blue box with a solid border. So far so good.
In my case I have some items which don't have a defined start and/or end date, so there might be open ends (from ever to ever).
To be honest I am struggling with both the 'conceptual' and the 'technical' solution how to display that within the timeline.
Currently I am just setting some very early/late date for open starts/ends but ideally it would be somehow visible to the user.
First idea that I had was to draw some infinite icon in the background of my item's div at the left for open start and/or at the right for open end.
Another idea would be to somehow fade out the endings of my div (some color grading from blue to alpha and get rid of the solid borders left and right).
Does anyone have a better idea (I guess so) and how would I have to overwrite the given CSS to reach that goal?
Yet I hope the question is clear and precise enough, if not please give me some chance to explain it into more detail.

How to modify behavior of a class depending on its top parent?

I have a .tintTile that depends on parent, hence the & sas follows:
// Tint titles
.tintTitle {
text-transform: uppercase;
font-family: #fontDemiBold;
color: #colorOrangeKWS;
.Windows7 & {
font-family: arial, sans-serif;
font-weight: bold;
color: #colorOrangeKWS;
}
}
In many others classes, I use the .tintTitle as follows:
// titles, orange bold
.tab {
&>div {
.tintTitle;
// etc.
}
}
Unfortunately, I can't achieve the .Windows7 (provided the fact Windows7 is a class set to the body tag as follows:
<body class="Windows7">
<p class="tintTitle">Good, it works</p>
<div class="tab">
<div>This title doesn't make it</div>
Is there a way to achieve my goal with less beside duplicating every .tintTitle where it's required?
As far as i understand your question your code should work in Less, see http://codepen.io/anon/pen/KwNWmq
Less code:
// Tint titles
.tintTitle {
text-transform: uppercase;
color: green;
.Windows7 & {
text-transform: initial;
color: red;
}
}
.tab {
&>div {
.tintTitle;
// etc.
}
}
Your are using the parent selectors feature of Less to change the selector order
The only thing you should notice will be that properties set for your (not having .windows) will be also applied for your .windows selectors. That's why i have to set text-transform: initial;, otherwise the .windows * also get uppercased cause the also match .tintTitle.

Change the size of the number input spinner?

On a number input it has a spinner which has several css properties but I can't seem to find a way to change the size of the spinner itself. I am talking about <input type='number'>. I tried finding something that would change the size but I haven't been able to find anything. The other issue I guess is that every browser on possibly every OS is going to have a potentially different implementation of the spinner itself. When I say spinner I am talking about the highlighted part of this image.
I cannot use the JQuery UI spinner because the large app I am developing uses JQuery UI 1.8 which did not include the spinner. Upgrading causes issues.
Not ideal, but try playing around with the CSS transform property:
For example,
input[type=number]
{
transform: scale(2);
}
This increases the size of the entire input, but maybe this (in conjunction with setting font-size, line-height, height, width) can produce a desired effect.
This CSS seems to work in Chrome by replacing the spinners with a static image (of a spinner) and then control the size and position of the image within the element and making it invisible by default until the user hovers over it:
* Spin Buttons modified */
input[type="number"].mod::-webkit-outer-spin-button,
input[type="number"].mod::-webkit-inner-spin-button {
-webkit-appearance: none;
background: #0F0 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKUlEQVQYlWNgwAT/sYhhKPiPT+F/LJgEsHv37v+EMGkmkuImoh2NoQAANlcun/q4OoYAAAAASUVORK5CYII=) no-repeat center center;
width: 3em;
border-left: 1px solid #0f0;
opacity: 0; /* shows Spin Buttons per default (Chrome >= 39) */
position: absolute;
top: 0;
right: 0;
bottom: 0;
}
input[type="number"].mod::-webkit-inner-spin-button:hover,
input[type="number"].mod::-webkit-inner-spin-button:active{
box-shadow: 0 0 2px #0CF;
opacity: .7;
}
Plain ole HTML...
No library or images required.
HTML
<!-- Score Control Container -->
<div class = "Score-Control">
<div class = "Score-Value-Container">
<div id="RoundScore" class="Score-Value">
10
</div>
</div>
<div class = "Score-UpDown">
<div class = "Score-Button-Container">
<div class = "Score-Button " onclick="IncrementScore();">
▲
</div>
</div>
<div class = "Score-Button-Container">
<div class = "Score-Button " onclick="DecrementScore();">
▼
</div>
</div>
</div>
</div>
CSS
.Score-Control {
width: 200px;
}
.Score-Value-Container{
position:relative;
display: table;
overflow: hidden;
height:80px;
background-color:#aaa;
width:66%;
float:left;
font-size: 44px;
vertical-align: middle;
text-align: center;
}
.Score-Value {
display: table-cell;
vertical-align: middle;
text-align: center;
}
.Score-UpDown{
position:relative;
height:80px;
background-color: burlywood;
width:34%;
float:right;
}
.Score-Button-Container {
display: table;
height: 50%;
width: 100%;
overflow: hidden;
background-color:green;
}
.Score-Button {
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 27px;
}
JavaScript
function IncrementScore() {
var RoundScore = document.getElementById("RoundScore").innerHTML;
if (RoundScore < 10) {
RoundScore++
document.getElementById("RoundScore").innerHTML = RoundScore;
}
}
function DecrementScore() {
var RoundScore = document.getElementById("RoundScore").innerHTML;
if (RoundScore > 1) {
RoundScore--
document.getElementById("RoundScore").innerHTML = RoundScore;
}
}
Code in JSFiddle
You could make an input field with two buttons for up and down and style them then the way you like.
<input type="text" name="something">
<span class="goUp"></span>
<span class="goDown"></span>
js:
var inputField = $('input[name="something"]');
$('.goUp').click(function() {
inputField.val(inputField.val() + 1);
});
$('.goDown').click(function() {
inputField.val(inputField.val() - 1);
});
you then should also check, that the input has only numbers inside, so that your +/- 1 really works.
The “size of the spinner” is a vague concept, but the <input type=number> element seems to obey at least width, height, and font property settings. Example:
<input type=number value=42 min=0 max=99
style="font: 24pt Courier; width: 3ch; height: 3em">
Whether such settings are useful and whether they should work is a different issue. It can be argued that the implementation of such elements is expected to be a browser-dependent nice, useable widget suitable for the browsing conditions, rather than something that authors should mess around with. But in practice, the widget is largely affected by CSS settings, and this might be a good thing in practice, e.g. because the input box tends to be too wide by default. (We could expect browsers to set it according to min and max values, but this just doesn’t happen at present.) The risk is that by setting the width, you might conflict with the implementation. The code above expects the up and down arrows to take a width of one character at most, but this guess might some day be wrong.

fail to change placeholder color with Bootstrap 3

Two questions:
I am trying to make the placeholder text white. But it doesn't work. I am using Bootstrap 3. JSFiddle demo
Another question is how do I change placeholder color not globally. That is, I have multiple fields, I want only one field to have white placeholder, all the others remain in default color.
html:
<form id="search-form" class="navbar-form navbar-left" role="search">
<div class="">
<div class="right-inner-addon"> <i class="icon-search search-submit"></i>
<input type="search" class="form-control" placeholder="search" />
</div>
</div>
</form>
css:
.right-inner-addon {
position: relative;
}
.right-inner-addon input {
padding-right: 30px;
background-color:#303030;
font-size: 13px;
color:white;
}
.right-inner-addon i {
position: absolute;
right: 0px;
padding: 10px 12px;
/* pointer-events: none; */
cursor: pointer;
color:white;
}
/* do not group these rules*/
::-webkit-input-placeholder { color: white; }
FF 4-18
:-moz-placeholder { color: white; }
FF 19+
::-moz-placeholder { color: white; }
IE 10+
:-ms-input-placeholder { color: white; }
Assign the placeholder to a class selector like this:
.form-control::-webkit-input-placeholder { color: white; } /* WebKit, Blink, Edge */
.form-control:-moz-placeholder { color: white; } /* Mozilla Firefox 4 to 18 */
.form-control::-moz-placeholder { color: white; } /* Mozilla Firefox 19+ */
.form-control:-ms-input-placeholder { color: white; } /* Internet Explorer 10-11 */
.form-control::-ms-input-placeholder { color: white; } /* Microsoft Edge */
It will work then since a stronger selector was probably overriding your global. I'm on a tablet so i cant inspect and confirm which stronger selector it was :) But it does work I tried it in your fiddle.
This also answers your second question. By assigning it to a class or id and giving an input only that class you can control what inputs to style.
There was an issue posted here about this: https://github.com/twbs/bootstrap/issues/14107
The issue was solved by this commit: https://github.com/twbs/bootstrap/commit/bd292ca3b89da982abf34473318c77ace3417fb5
The solution therefore is to override it back to #999 and not white as suggested (and also overriding all bootstraps styles, not just for webkit-styles):
.form-control::-moz-placeholder {
color: #999;
}
.form-control:-ms-input-placeholder {
color: #999;
}
.form-control::-webkit-input-placeholder {
color: #999;
}
A Possible Gotcha
Recommended Sanity Check - Make sure to add the form-control class to your inputs.
If you have bootstrap css loaded on your page, but your inputs don't have the
class="form-control" then placeholder CSS selector won't apply to them.
Example markup from the docs:
I know this didn't apply to the OP's markup but as I missed this at first and spent a little bit of effort trying to debug it, I'm posting this answer to help others.
I'm using Bootstrap 4 and Dennis Puzak's solution does not work for me.
The next solution works for me
.form-control::placeholder { color: white;} /* Chrome, Firefox, Opera*/
:-ms-input-placeholder.form-control { color: white; } /* Internet Explorer*/
.form-control::-ms-input-placeholder { color: white; } /* Microsoft Edge*/
Bootstrap has 3 lines of CSS, within your bootstrap.css generated file that control the placeholder text color:
.form-control::-moz-placeholder {
color: #999999;
opacity: 1;
}
.form-control:-ms-input-placeholder {
color: #999999;
}
.form-control::-webkit-input-placeholder {
color: #999999;
}
Now if you add this to your own CSS file it won't override bootstrap's because it is less specific. So assmuning your form inside a then add that to your CSS:
form .form-control::-moz-placeholder {
color: #fff;
opacity: 1;
}
form .form-control:-ms-input-placeholder {
color: #fff;
}
form .form-control::-webkit-input-placeholder {
color: #fff;
}
Voila that will override bootstrap's CSS.
The others did not work in my case (Bootstrap 4). Here is the solution I used.
html .form-control::-webkit-input-placeholder { color:white; }
html .form-control:-moz-placeholder { color:white; }
html .form-control::-moz-placeholder { color:white; }
html .form-control:-ms-input-placeholder { color:white; }
If we use a stronger selector (html first), we don't need to use the hacky value !important.
This overrides bootstraps CSS as we use a higher level of specificity to target .form-control elements (html first instead of .form-control first).
I think qwertzman is on the right track for the best solution to this.
If you only wanted to style a specific placeholder, then his answer still holds true.
But if you want to override the colour of all placeholders, (which is more probable) and if you are already compiling your own custom Bootstrap LESS, the answer is even simpler!
Override this LESS variable:
#input-color-placeholder
Boostrap Placeholder Mixin:
#mixin placeholder($color: $input-color-placeholder) {
// Firefox
&::-moz-placeholder {
color: $color;
opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526
}
&:-ms-input-placeholder { color: $color; } // Internet Explorer 10+
&::-webkit-input-placeholder { color: $color; } // Safari and Chrome
}
now call it:
#include placeholder($white);
You should check out this answer : Change an HTML5 input's placeholder color with CSS
Work on most browser, the solution in this thread is not working on FF 30+ for example
With LESS the actual mixin is in vendor-prefixes.less
.placeholder(#color: #input-color-placeholder) {
...
}
This mixin is called in forms.less on line 133:
.placeholder();
Your solution in LESS is:
.placeholder(#fff);
Imho the best way to go. Just use Winless or a composer compiler like Gulp/Grunt works, too and even better/faster.

Resources