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.
Related
I am doing a project that has a input like this:
<div className="search__bar__description form__control">
<input
placeholder="Filter by title, companies, expertise..."
aria-label="Enter company, title, or expertise here"
onChange={e => setSearchInput(e.target.value)}
value={searchInput}
/>
</div>
When the site is in desktop I want to have that whole long placeholder but when in mobile I want the placeholder just to say Filter by title...
I am trying to figure out how to do this is CSS. Can I put a span inside of the placeholder & then just hide it? Would that be valid HTML? If it isn't W3C valid HTML can you please tell me how to do this?
Thanks in advance!
First, you don't need JavaScript to do this. Although you cannot put a span inside an input, you can perform some trickery using the :placeholder-shown pseudo-class to achieve what you're after. Browser support for this pseudo-class, at the time of this post, is really good.
From MDN:
The :placeholder-shown CSS pseudo-class represents any <input> or
<textarea> element that is currently displaying placeholder text.
This example makes the input placeholder color transparent on smaller-sized screens, visually hiding it. The span containing the short label is then shown at this break point. Notice it's styled and positioned so that it looks as close to the original placeholder text as possible. Finally, using the pseudo-class mentioned above, we hide the short label when the original placeholder is not shown (when input is not blank).
.form__control {
position: relative;
}
.short-label {
display: none;
pointer-events: none;
}
#media screen and (max-width: 700px) {
::placeholder {
color: transparent;
}
.short-label {
position: absolute;
left: 4px;
top: calc(50% + 1px);
transform: translateY(-50%);
font-size: 11px;
color: rgb(43%, 43%, 43%);
font-family: sans-serif;
letter-spacing: 0.4px;
display: block;
font-weight: lighter;
}
input:not(:placeholder-shown)+.short-label {
display: none;
}
}
<div class="search__bar__description form__control">
<input placeholder="Filter by title, companies, expertise..." aria-label="Enter company, title, or expertise here" />
<span class="short-label">Filter by title...</span>
</div>
jsFiddle
You can't put a span inside a placeholder.
The common solution to what you want to achieve is to have the placeholder text as a separate element, underlaid behind the text field. And then you can do whatever markup and styling you want to it. This, of course, is more effort, but such is the way of bespoke engineering.
You can see an advanced example here: https://css-tricks.com/float-labels-css/
If you ignore the animations, the take-away from his code example is that the <label> element is used instead of the placeholder attribute, and is underlaid behind the input field, so it looks the same, but then can be manipulated with all the same CSS (int his case, adding some fancy transitions) and sub-elements as any other standard element.
I am trying to underline an <input type="date"> field using style="text-decoration: underline;" but it doesn't seem to work. Is there another way to underline the set date value? I would also like to apply this for time.
NOTE I am able to apply font-weight and color properties to these inputs but not text-decoration
EDIT
It seems the above is not a sufficient explanation of what I am trying to achieve.
Basically:
<input type="date"> will yield 15-02-17
I am trying something like:
<input type="date" style="text-decoration: underline;"> to yield an underlined 15-02-17
But this does not work. Is there another way?
ANOTHER EDIT
Preferably the solution should be generalized to all browsers.
Put this code in the CSS.
input::-webkit-datetime-edit-fields-wrapper {
text-decoration:underline;
}
The date tag consists of different div and span tags, which are enveloped by input::-webkit-datetime-edit-fields-wrapper in Chrome
EDIT : Example date input tag in Chrome
I'm not sure you can style <input type="date"> with text-decoration.
Not the nicest solution, but you could manually add an underline..
.wrap {
position: relative;
display: inline-block;
}
.wrap:after {
content: '';
position: absolute;
bottom: 2px;
left: 4px;
height: 1px;
width: 54%;
background: red;
}
<div class="wrap">
<input type="date">
</div>
CODEPEN
Note that you can't add pseudoelement to input, so you'll have to position it relative to something else.
I'm affraid the visualization of html5 inputs is browser-specific (kinda like fieldsets), thats why text-decoration: underline; won't work. You will likely run into issues too when trying to style the calendar it is showing.
I think your best bet is to use a plugin. There are plenty ot there, ie: https://github.com/fengyuanchen/datepicker
Also, you can edit your question and ask for the specific browser you want to do this, I'm sure we can find out the style needed.
The problem
I cannot alter the way in whcih the HTML below is output, but I do need to amend the way in which it is displayed. I know I can achieve my desired results with jQuery, but I'd like to do it with pure CSS possible?
What exactly I need to do
I need to show the input from the HTML below, but the label itself is superfluous. The tag can stay or go, I'm not bothered by that, but Username and <br> need to be gone.
Obviousely I cannot use label[for="user_login"]{ display: none; }, as this will fail because it will hide everything within the selector.
The original HTML
<label for="user_login">
Username
<br>
<input id="user_login" class="input" type="text" size="20" value="" name="log">
</label>
The desired HTML
<label for="user_login">
<input id="user_login" class="input" type="text" size="20" value="" name="log">
</label>
jQuery approach
$(document).ready(function(){
var username_label = $('label[for="user_login"]'),
username_input = username_label.find('input');
username_label.html(username_input);
});
Why I don't want to use jQuery
The login for in question is displayed differently depending on screen size. On smaller devices I requre the labels hidden (to save space), while on larger screens the label should still be visible. Using the jQuery approach will remove the labels in both cases.
While I know I can check the screen widht on load, and then use resize event (if necessary), should the screen size change (on a tablet, portrait to landscape for example) the labels could be removed and then not visible when they need to be.
Question
Can I achieve this result (or similar) with pure CSS?
Try this css:
label {
visibility:collapse;
}
label input {
visibility: visible;
}
Here is a jsfiddle:
http://jsfiddle.net/entgqjzk/
I modified the css I found at Hide text node in element, but not children
edit:
This doesn't remove the whitespace as you indicated.
I can't come up with anything better than a combination of jQuery and css, it's not the most beautiful code ever but it does work for this situation in which you don't have control over the html:
http://jsfiddle.net/entgqjzk/2/
The css class "hidden-for-mobile" could be used for example combined with a seperate stylesheet for mobile devices (or pseudo selectors for different screen sizes)
Have you tried pseudo classes? http://css-tricks.com/a-call-for-nth-everything/
Thanks to #geoffreydv for the idea of using visibility.
In conjunction with that, I was able to use the CSS below to effectively hide the whitespace occuped by the text within the label.
body.login #loginform label[for="user_login"],
body.login #loginform label[for="user_pass"]{
display: inline-block;
height: 50px;
position: relative;
visibility: collapse;
width: 300px;
}
body.login #loginform input#user_login,
body.login #loginform input#user_pass{
margin: 0;
position: absolute;
top: 0;
visibility: visible;
width: 300px;
}
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
Let's have a label element with the for attribute specified properly. This label will later have some action bound on click event, so we want to change the label's appearance on hover to indicate the option to click it.
However, if you open IE 10/11 and put your cursor over the label's corresponding input element, the label's :hover pseudoclass will activate!
I tried floatng the label and input and setting position: absolute.
The only solution I could find was to change/remove label's for or input's id so they wouldn't be connected to each other. But this is not a good solution, since it disconnects these two elements semantically and will probably lead to issues with screen readers. Is there any other way to resolve this bug?
JSFiddle: fiddle
JSFidde with broken for-id link: fiddle
You don't have to use "for" at all if you change your HTML structure a little bit. And yes, label and input are still "connected".
<div>
<label>
<span>label</span>
<input id="test" type="text">
</label>
</div>
Here is example: http://jsfiddle.net/Vq8kN/8/
if you want you can get your goal with 2 lines of jquery (I don't know if you can use it)
working demo
$("input").hover(function(){
$("label").removeClass('hovertest');
}).mouseout(function(){
$("label").addClass('hovertest');
});
css
div {
margin: 1em auto;
width: 300px;
padding: 0.2em;
border: 1px dotted black;
}
label {
padding: 0.2em 1em;
}
input {
width: 200px;
}
.hovertest:hover {
background: #ccc;
cursor: pointer;
}
html
<div>
<label class="hovertest" for="test">label</label>
<input id="test" type="text"/>
</div>