How to change the color of the placeholder in vaadin-select

So, I create a select component, associated an ID to later modify it in css:

As you can see from the screenshot, the event search is a text field and I can change the color of the placeholder and value, like this:

#eventSearchLayout vaadin-text-field::part(value){
	cursor: auto;
	color: white !important;
}

I can also change the select value (when choosing an item):

#statusSearchLayout vaadin-select::part(value),
#categorySearchLayout vaadin-select::part(value){
	cursor: auto;
	color: white !important;
}

But when trying to change the color of the placeholder, nothing happens, is it a vaadin bug?
I already try with

::part(value)::-webkit-input-placeholder {...}
::part(value)::placeholder{...} -> this works for textField and textArea but not select
::placeholder{...}
#categorySearchLayout vaadin-select::part(value)::placeholder{...}
vaadin-select-text-field::part(input-field){...}

But nothing work.

I also put here a screenshot of the structure when inspecting the select

18479612.png
18479615.png
18479618.png

Hi Tiago,

This is actually quite interesting, and I’m going to have to look into it a bit closer when I have time.

I’m pretty sure this is not an issue in vaadin-select per se, but in the browser’s implementation of the ::part() selector. Unless I’m mistaken ::part() is not supposed to work on nested shadow roots at all, which is what we’re dealing with here, in that the value part is actually part of the vaadin-text-field component inside vaadin-select. So I did not expected vaadin-select::part(value) to work at all, but for some reason it does (at least in Chrome and Firefox).

Meanwhile, I think the easiest solution is to either
a) Use the --lumo-body-text-color css property to override both the value and the placeholder color to e.g. white, i.e.
#statusSearchLayout { --lumo-body-text-color: white; }
or
b) Inject your css directly into the shadow dom of vaadin-text-field using @CssImport with themeFor (see https://vaadin.com/docs/v14/themes/styling-components.html and https://vaadin.com/docs/v14/themes/importing-style-sheets.html#component-styles)

Rolf Smeds:
Hi Tiago,

This is actually quite interesting, and I’m going to have to look into it a bit closer when I have time.

I’m pretty sure this is not an issue in vaadin-select per se, but in the browser’s implementation of the ::part() selector. Unless I’m mistaken ::part() is not supposed to work on nested shadow roots at all, which is what we’re dealing with here, in that the value part is actually part of the vaadin-text-field component inside vaadin-select. So I did not expected vaadin-select::part(value) to work at all, but for some reason it does (at least in Chrome and Firefox).

Meanwhile, I think the easiest solution is to either
a) Use the --lumo-body-text-color css property to override both the value and the placeholder color to e.g. white, i.e.
#statusSearchLayout { --lumo-body-text-color: white; }
or
b) Inject your css directly into the shadow dom of vaadin-text-field using @CssImport with themeFor (see https://vaadin.com/docs/v14/themes/styling-components.html and https://vaadin.com/docs/v14/themes/importing-style-sheets.html#component-styles)

Thank you so much for the fast reply! the solution a) works perfectly :slight_smile:

Followup to the above:

The reason why vaadin-select::part(value) works for styling the text representing the selected value is that it’s actually rendered as a vaadin-item element slotted into the text-field, replacing the its normal value part, which means that it’s part of the select’s shadow dom rather than that of the text-field, thus accessible as a part of vaadin-select.

However, when no value is selected, and the placeholder is shown, the built-in value part of the internal vaadin-text-field is used instead, and because the value is in that case part of the text-field inside select, and not a direct part of the select component itself, a ::part selector on vaadin-select can’t reach it.

The reason for this arrangement is that by using a vaadin-item to show the selected value, the component can support rich content for rendering the value (e.g. icons), whereas when no value is selected, the placeholder feature of vaadin-text-field is utilized instead of re-implementing the same functionality as part of vaadin-select.

So the root problem is really the limitations of the ::part selector. The [exportparts attribute]
(https://www.w3.org/TR/css-shadow-parts-1/#exportparts-attr) will solve many of the shortcomings of ::part selectors, but we haven’t applied that to Vaadin components yet due to lacking browser support. This will be added in a future version, however, and in the meantime you can bypass the entire issue by using the @CssImport annotation with the themeFor parameter to inject any css anywhere inside a component.