1

I found solution for :required inputs but nothing for :optional.

Thank you for help and sorry for my English, this isn't my native language.

pgpb.padilla
  • 2,318
  • 2
  • 20
  • 44
Irina Zorg
  • 83
  • 6
  • When do you want to highlight the input? Perhaps when the user hovers above it or have a focus on that field? – user0101 May 27 '20 at 09:06

3 Answers3

2

Found this solution, using :placeholder-shown:

input:placeholder-shown {
  border: 1px solid #f5f5f5;
}

input {
  background: #ffffff;
  border: 10px solid;
  border-image-slice: 1;
  border-width: 1px;
  border-image-source: linear-gradient(
    171.2deg,
    #ffc1d4 15.78%,
    #ff866c 76.58%
  );
}
<form>
  <input type="text" name="name1" id="" placeholder="placeholder1" optional>
  <input type="text" name="name2" id="" placeholder="placeholder2" optional>
</form>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Irina Zorg
  • 83
  • 6
  • Very cool!! Beware that `:placeholder-shown` doesn't work in any version of IE, and doesn't work in Edge v44 or earlier (which are still current on most Windows installations -- though not for much longer, since Chromium-based Edge v79 came out in January and is incrementally being added to auto-update). – T.J. Crowder May 27 '20 at 09:29
  • Note that you'll still want `:not(:required)` or similar to avoid styling required elements. – T.J. Crowder May 27 '20 at 09:35
  • Ah! But see the comment on [this answer](https://stackoverflow.com/a/35593489/157247): There's a Microsoft-specific version that works on IE: `:-ms-input-placeholder`. So if you use both (in separate but equivalent rules), you're covered for IE and Edge v44 and before. – T.J. Crowder May 27 '20 at 09:42
1

Note: If you're targeting modern browsers and using a placeholder (or you can use a placeholder), you can use Irina's :placeholder-shown pseudo-class below rather than .empty) and do away with the JavaScript. It doesn't work in IE or Edge v44 or earlier, but works in all up-to-date modern browsers. But: You can use -ms-input-placeholder for IE and Edge v44 and earlier, making the JavaScript part of the below defunct. But I don't want to edit it to use :placeholder-shown and :-ms-input-placeholder because that duplicates Irina's answer (somewhat), and I can't remove this answer because it's accepted. See the end of the answer for an example, though.


I found solution for :required inputs but nothing for :optional.

Two ways you can do that:

  1. You can use :not(:required). :not is the negation pseudoclass. It accepts a simple selector and inverts its meaning. "Not required" is "optional."

  2. You can style all of the inputs in the "optional" way, then override that styling for :required elements.

Unfortunately, though, the "empty" part of your question can't be answered with CSS alone for input elements that are optional (more here).

Here's an example of #1, using JavaScript to add/remove a class when the input is/isn't empty:

"use strict";
function toggleEmptyClass(el) {
    if (el.tagName === "INPUT") {
        // If you need IE compatibility, you'll need an `if`/`else`;
        // IE doesn't support the second argument for `toggle`
        el.classList.toggle("empty", !el.value);
    }
}
document.querySelectorAll("input").forEach(toggleEmptyClass);
document.addEventListener("input", function() {
    toggleEmptyClass(event.target);
});
input:not(.empty):required {
    background-color: #FF8000;
}
input:not(.empty):not(:required) {
    background-color: #0080FF;
}
<div>
    <label>
        Required:
        <input type="text" required value="required">
    </label>
</div>
<div>
    <label>
        Required and (initially) empty:
        <input type="text" required>
    </label>
</div>
<div>
    <label>
        Optional:
        <input type="text" value="optional">
    </label>
</div>
<div>
    <label>
        Optional and (initially) empty:
        <input type="text">
    </label>
</div>

Or you can just style all input elements with the "optional" style, and then override it for :required elements:

Example:

"use strict";
function toggleEmptyClass(el) {
    if (el.tagName === "INPUT") {
        // If you need IE compatibility, you'll need an `if`/`else`;
        // IE doesn't support the second argument for `toggle`
        el.classList.toggle("empty", !el.value);
    }
}
document.querySelectorAll("input").forEach(toggleEmptyClass);
document.addEventListener("input", function() {
    toggleEmptyClass(event.target);
});
input:not(.empty) {
    background-color: #0080FF;
}
input:not(.empty):required {
    background-color: #FF8000;
}
<div>
    <label>
        Required:
        <input type="text" required value="required">
    </label>
</div>
<div>
    <label>
        Required and (initially) empty:
        <input type="text" required>
    </label>
</div>
<div>
    <label>
        Optional:
        <input type="text" value="optional">
    </label>
</div>
<div>
    <label>
        Optional and (initially) empty:
        <input type="text">
    </label>
</div>

Here's a full example showing doing the above with :placeholder-shown and the older Microsoft-specific -ms-input-placeholder:

input:not(:placeholder-shown):required {
    background-color: #FF8000;
}
input:not(:placeholder-shown):not(:required) {
    background-color: #0080FF;
}
/* IE and Edge <= v44 support: */
input:not(:-ms-input-placeholder):required {
    background-color: #FF8000;
}
input:not(:-ms-input-placeholder):not(:required) {
    background-color: #0080FF;
}
<div>
    <label>
        Required:
        <input type="text" placeholder="placeholder" required value="required">
    </label>
</div>
<div>
    <label>
        Required and (initially) empty:
        <input type="text" placeholder="placeholder" required>
    </label>
</div>
<div>
    <label>
        Optional:
        <input type="text" placeholder="placeholder" value="optional">
    </label>
</div>
<div>
    <label>
        Optional and (initially) empty:
        <input type="text" placeholder="placeholder">
    </label>
</div>

Or, again, styling all of them and then overriding just the :required to be different:

input:not(:placeholder-shown) {
    background-color: #0080FF;
}
input:not(:placeholder-shown):required {
    background-color: #FF8000;
}
/* IE and Edge <= v44 support: */
input:not(:-ms-input-placeholder) {
    background-color: #0080FF;
}
input:not(:-ms-input-placeholder):required {
    background-color: #FF8000;
}
<div>
    <label>
        Required:
        <input type="text" placeholder="placeholder" required value="required">
    </label>
</div>
<div>
    <label>
        Required and (initially) empty:
        <input type="text" placeholder="placeholder" required>
    </label>
</div>
<div>
    <label>
        Optional:
        <input type="text" placeholder="placeholder" value="optional">
    </label>
</div>
<div>
    <label>
        Optional and (initially) empty:
        <input type="text" placeholder="placeholder">
    </label>
</div>
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Can't use this method. In this case the styles will be shown always, but I need them only in case when input is not empty. – Irina Zorg May 27 '20 at 09:09
  • @IrinaZorg - Unfortunately, there is no CSS selector for an empty/non-empty `input` element, only valid/invalid, which (I think you already know) doesn't help with optional inputs. You need to use JavaScript for that. :-( – T.J. Crowder May 27 '20 at 09:16
  • @IrinaZorg are you looking for this: https://jsfiddle.net/ogzw0a64/1/ ? – Temani Afif May 27 '20 at 09:25
  • @IrinaZorg - I've updated the answer to show using JavaScript to toggle a class for use in the CSS. – T.J. Crowder May 27 '20 at 09:25
-1

Here's a solution using javascript and css

CSS:

.highlighted
      {
        border: hsl(180, 60%, 60%) 2px solid;
      }

JS:

        let inputs = document.querySelectorAll('input:optional');
        for (let input of inputs)
        {
            input.addEventListener('change',function(e)
            {
              if (this.value != '')
              {
                this.classList.add('highlighted');
              }
              else
              {
                this.classList.remove('highlighted');
              }
            });
        }