How to make default style work when checking validation? - html

input {
background: white;
color: white;
}
input:in-range {
background: green;
color: white;
}
input:out-of-range {
background: red;
color: white;
}
<h3> CSS range validation </h3>
Enter your age
<input type="number" min="1" max="100">
Aim:
white for out-of-range (default case)
green for in-range
red for out-of-range
In the above snippet, how can one make
input {
background: white;
color: white;
}
work for just input regardless of in-range or out-of-range?

It seems like the :in-range and :out-of-range pseudo-classes work similar to the :valid and the :invalid pseudo-selectors. When this is applied, the input always seems to be in of the two states and because of it the default selector never gets applied. A blank value is also getting treated as in the range (though it shouldn't be). The selectors spec doesn't seem to mention a handling for this case.
Ideally, I would recommend adding a default value for the field (like value="0") because it is anyway a mandatory field for you. But, if you feel that the default red background affects your UX in a bad way then have a look at the below workaround.
Adding required attribute to the input (because it is anyway mandatory) and using it along with the :valid and :invalid pseudo-selectors seem to produce the required output.
input:invalid - Applied for default scenario or blank value because field is required and so a blank value means invalid.
input:in-range:valid - Any value that is in range and is valid would meet this selector.
input:out-of-range:invalid - Any value that is out of range and invalid only because it is out of range will match this selector and so red color would come only when the value is out of range.
Note to future readers: This is also not very correct because if I am a user, I would expect a blank value for a required field also to be invalid and have a red background. So, this may not be a suitable workaround for you. Please validate and use accordingly.
input:invalid {
background: white;
color: white;
}
input:in-range:valid {
background: green;
color: white;
}
input:out-of-range:invalid {
background: red;
color: white;
}
<h3> CSS range validation </h3>
Enter your age
<input type="number" min="1" max="100" required>

CSS cannot check whether or not a text box is empty under the conditions you are looking for. Below is a better approach to the solution, however your solution will require JavaScript. Please see this thread.
Try adding a class where the styles are only applied if the classes are on the element.
CSS
input[type="number"] {
background: white;
color: black;
}
input[type="number"].validate:in-range {
background: green;
color: white;
}
input[type="number"].validate:out-of-range {
background: red;
color: white;
}
HTML
<h3> CSS range validation </h3>
Enter your age
<input class="validate" type="number" min="1" max="100">
<h3> NO CSS range validation </h3>
Enter your age
<input type="number" min="1" max="100">

Related

How to make an input (radio?) look like a toggle/slider between two choices?

I’m brand new to coding and a project I’m working on in class is a registration form. It needs to have an input for “Male” or “Female” that looks like a toggle. I assumed it is a radio button that’s made to look like a toggle in CSS but from what I’ve read the workarounds are very complex to do that, or you need to use JS or something that we haven’t learned yet.
I think I’m close on the rest of it but I can’t get that male/female input!
what I’m tasked with replicating:
I assumed it is a radio button that’s made to look like a toggle
You're right (at least to think of using radio buttons), these are two inputs of type radio with an associated label for each one that are (the labels) styled using CSS.
To be short, here's a live demo of the end result :
.wrapper {
display: flex;
padding: 4px;
background-color: #24ef43;
}
.custom-input {
flex-grow: 1;
}
.custom-input input[type=radio] {
display: none;
}
.custom-input label {
display: block;
padding: 6px 8px;
color: #fff;
font-weight: bold;
text-align: center;
transition : all .4s 0s ease;
}
.custom-input input[type=radio]:checked + label {
background-color: #f5f5f5;
color: #000;
border-radius: 4px;
}
<div class="wrapper">
<div class="custom-input">
<input type="radio" id="female" name="gender">
<label for="female">Female</label>
</div>
<div class="custom-input">
<input type="radio" id="male" name="gender">
<label for="male">Male</label>
</div>
</div>
Disclaimer: I tried to be as short as possible in my answer, also wanted to put the OP on the track thus I didn't use any best practices or patterns nor give attention to accessibility in the code above. Also, I didn't make any clarifications about the code being used so it up to the OP to ask for any further assistance and am glad to provide some help.

Label transition is not working in case of validations with React-hook-form

I am trying to apply a styling which moves the label to top when the input is in focus.
It was working very well before I tried to add validation.
Sample Code:-
<form onSubmit={handleSubmit(onSubmit)}>
<div className="form__group">
<input
className="form__input"
type="text"
id="name"
name="name"
placeholder=" "
ref={register}
/>
{errors.name && <p className="error">{errors.name.message}</p>}
<label className="form__label" htmlFor="name">
Name
</label>
</div>
<input type="submit" />
</form>
Normaly if you focus on Input the transition works in the start. The
problem is arising when when any validation is not satisfied on
submission and an error is being shown.
If on submitting form,validation is not satisfied then error messages
are fired as per the validation but in this case the transition is
not applied even though the input is in focus.
As long as the error is visible the styling is not applied and I
can't understand why. So far I have deducted that it is overriding the
styling of my label.I can't seem to find a way across it.
The styling that is mentioned is:-
.form__label {
position: absolute;
color: #777777;
transition: all 0.3s;
cursor: text;
top: 16%;
left: 6.5%;
}
form__input {
&:focus {
border: 2px solid blue;
& + .form__label {
top: 3px;
left: 10px;
color: blue;
}
}
&:not(:placeholder-shown) + .form__label {
top: 3px;
left: 10px;
color: blue;
}
}
The sandbox of the above problem is here
The Problem is that direct sibling is selected in the above case instead of "+" combinator ,"~" combinator should have been used.
"+" combinator selects the direct sibling which in case of no errors is the label. so it works in the start but fails in other cases.
"~" combinator selects the general sibling which will work in all cases.
In case of errors the label is not a direct sibling that is causing the problem.

CSS: Detect input with valid data not focused with no javascript

I have been checking similar questions in Stackoverflow, but I can't find the proper way to do this:
I want an input without border. When focused, border is blue. Also, when not focused but with text added inside it, border should be blue as well.
I am trying with .Input:focus, .Input:not(:focus):valid {}, with no result: the rule is triggered when the inut is not focused or with text, I add an example:
.Input {
border: none;
outline: none;
}
.Input:focus,
.Input:not(:focus):valid {
border: 2px solid blue;
}
<input class="Input" type="text" name="EMAIL" id="email" placeholder="email">
Any idea will be welcome!
This should work for you:
.Input[value=""], .Input:placeholder-shown {
border: none;
outline: none;
}
.Input, .Input:focus {
border: 2px solid blue;
}
By default, the input field will always have a blue border. The two selectors above it, however, will determine whether to show the border or not.
If the input field has an empty value, or if the placeholder text is displaying, then the border will be removed and the field will have no decoration. Otherwise, if the input doesn't match any of this criteria, it will have a blue border.
The :focus attribute is used to ensure that the field will have a blue border when it is selected but doesn't contain any text, or when it only contains placeholder text.
Hope this helps!
:valid works when the content of the input passes all validation rules placed on it. In your case, since it is an email, you can change the type from text to email. Any text entered into the input that doesn't match the default HTML Email pattern won't trigger the :valid pseudo class.
In order for your input to be "invalid" when it is empty you can add required to your input. Since it is defaulted to being empty it will not be valid as it is required.
.Input {
border: none;
outline: none;
}
.Input:focus,
.Input:not(:focus):valid {
border: 2px solid blue;
}
<input class="Input" type="email" required name="EMAIL" id="email" placeholder="email">
Additionally you can use the pattern attribute which accepts a Javascript regex string to validate your input on. For example purposes only you can use a pattern like [a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,3}$. By default the input is empty and is invalid. Same goes for any string that doesn't match something#something.com or something123#something123.eu as examples.
.Input {
border: none;
outline: none;
}
.Input:focus,
.Input:not(:focus):valid {
border: 2px solid blue;
}
<input class="Input" type="email" pattern="[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,3}$" required name="EMAIL" id="email" placeholder="email">

2 colors in one placeholder of input field

I need create input which has 2 colors in a placeholder.
and here is solution which works well in Chrome.
http://jsfiddle.net/vmuJm/
html
<input placeholder="Name" class="required" />
css
.required::-webkit-input-placeholder:after {
content:'*';
color: red;
}
.required:-moz-placeholder:after {
/* Firefox 18- */
content:'*';
color: red;
}
.required::-moz-placeholder:after {
/* Firefox 19+ */
content:'*';
color: red;
}
.required:-ms-input-placeholder:after {
content:'*';
color: red;
}
But my current FF 29.0.1 doesn't show content from :after, so this solution doesn't work. Is there any other way to get 2 colors in one placeholder with css and html?
Chrome:
FF:
Here is a cross-browser solution that does not use Javascript:
Live demo
Inline elements such input do not support :before and :after. To make things even harder the placeholder selector and their pseudo-classes are not fully supported by all browsers, as you found out.
So, the workaround is to add a label placed relatively on top of the input box with a for attribute pointing to the input text box. This way, when user clicks the label (fake placeholder) the focus goes into the input box underneath.
Replace your class="required" by the attribute required="required". This gives you an opportunity to use the :invalid and :valid selectors, and also lets the browser display a validation error, when the form is submitted with empty required fields.
input {
width: 160px;
}
input[type=submit] {
width: auto;
}
input[required]+label {
color: #999;
font-family: Arial;
font-size: .8em;
position: relative;
left: -166px;
/* the negative of the input width */
}
input[required]+label:after {
content: '*';
color: red;
}
/* show the placeholder when input has no content (no content = invalid) */
input[required]:invalid+label {
display: inline-block;
}
/* hide the placeholder when input has some text typed in */
input[required]:valid+label {
display: none;
}
<form>
<input type="text" id="name" name="name" required="required" />
<label for="name">Name</label>
<br/>
<input type="email" id="email" name="email" placeholder="Email" />
<br/>
<input type="submit" />
</form>
Since the email is not required, leave the native placeholder there, and just to this hack for the name.
I also changed your email from type="text" to type="email" for better user experience on mobile devices.
Inspired by Jose's solution, without using "required" attribute, the live demo also can do what you want.
Key point is css has :not selector, refer to Mozilla website
Same question is asked here
Basically the answer is no. Depends on the browser.
:before and :after can not be used on some elements such as <input>. It Depends on the browser though, as it seems like chrome can do it.
Maybe it can be solved using JavaScript? I don't know

Placeholder text in an input field with CSS only (no JavaScript)

Instead of labeling each field in a form, it is sometimes preferable (from a design standpoint) to have placeholder text in each field. For example, instead of having this:
----------------------------------
Full Name: | |
----------------------------------
you have this:
----------------------------------
| Full Name |
----------------------------------
The when you click in the field, the text disappears and you can write whatever you want. If you skip over the field without entering any text, then the placeholder reappears.
I've seen this done many ways, but all methods involve JavaScript. For example, Twitter does a decent job on their signup page but if Javascript is disabled you end up typing your name over the word 'Full name'.
I'm looking for a CSS-only method that would work even with JavaScript disabled. The only potential solution I've come up with is to set the background of the <input> tag to an image of the desired text and then use the input:focus pseudo-class to clear the background image when someone clicks on the text box. This seems to work but it would be nice not to have to use images.
Does anyone know of a good resource on how to do this?
This is the preferred method, and works in all current browsers:
<input type="text" name="" placeholder="Full Name"/>
This version works for IE9 and before:
<input type="text" name="" value="Full Name" onfocus="value=''" onblur="value='Full Name'"/>
You can do this with a <label> placed behind the index using z-index and a transparent background-color on the <input>. Use :focus to change to a white background.
:first-line has some Firefox issues.
Demo: http://jsfiddle.net/ThinkingStiff/bvJ43/
Note: See code-sushi's comment below for blur issues: Placeholder text in an input field with CSS only (no JavaScript)
Output:
HTML:
<label class="input">enter name<input /><label>​
CSS:
.input {
color: gray;
display: block;
font-size: small;
padding-top: 3px;
position: relative;
text-indent: 5px;
}
input {
background-color: transparent;
left: 0;
position: absolute;
top: 0;
z-index: 1;
}
input:focus, input:first-line {
background-color: white;
}
Try this:
HTML
<div>
<input type="text" id="text"></input>
<label for="text">required</label>
</div>
CSS
.text-wrapper {
position: relative;
}
.text-input-label {
position: absolute;
/* left and right properties are based on margin, border, outline and padding of the input text field */
left: 5px;
top: 3px;
color: #D1D1D1;
}
#text:focus + label {
display: none;
}
Working Fiddle
All of the presumably CSS-only answers above have neglected a critical component which is required in order to prevent the label acting as a pseudo-placeholder from "bleeding through" once the user is no longer focused on that particular field.
Hint:
input:valid { background-color:white; }
The pseudo-class :valid obtains whenever a field has any value other than ''. So when your user enters anything in the field of his or her own, the label displayed there will stop being displayed.
Be advised with <input type="email" /> fields, the pseudo-class :valid does and will actually require input of a valid email format (e.g. "xxxx#xxx.com" -- or .net or .org, etc.).
Full instructions how to do this here: http://css-tricks.com/float-labels-css/
Try this: it solves the overflowing placeholder and multi-input cases. The trick is to move the labels behind their inputs and reorder them visually.
You don't need an extra div to achieve what you want.