How to style readonly attribute with CSS? - html

I'm currently using readonly="readonly" to disable fields. I'm now trying to style the attribute using CSS. I've tried using
input[readonly] {
/* styling info here */
}
but it is not working for some reason. I've also tried
input[readonly='readonly'] {
/* styling info here */
}
that doesn't work either.
How can I style the readonly attribute with CSS?

input[readonly]
{
background-color:blue;
}
https://curtistimson.co.uk/post/css/style-readonly-attribute-css/

Note that textarea[readonly="readonly"] works if you set readonly="readonly" in HTML but it does NOT work if you set the readOnly-attribute to true or "readonly" via JavaScript.
For the CSS selector to work if you set readOnly with JavaScript you have to use the selector textarea[readonly].
Same behavior in Firefox 14 and Chrome 20.
To be on the safe side, i use both selectors.
textarea[readonly="readonly"], textarea[readonly] {
...
}

Loads of answers here, but haven't seen the one I use:
input[type="text"]:read-only { color: blue; }
Note the dash in the pseudo selector. If the input is readonly="false" it'll catch that too since this selector catches the presence of readonly regardless of the value. Technically false is invalid according to specs, but the internet is not a perfect world. If you need to cover that case, you can do this:
input[type="text"]:read-only:not([read-only="false"]) { color: blue; }
textarea works the same way:
textarea:read-only:not([read-only="false"]) { color: blue; }
Keep in mind that html now supports not only type="text", but a slew of other textual types such a number, tel, email, date, time, url, etc. Each would need to be added to the selector.

To be safe you may want to use both...
input[readonly], input[readonly="readonly"] {
/*styling info here*/
}
The readonly attribute is a "boolean attribute", which can be either blank or "readonly" (the only valid values). http://www.whatwg.org/specs/web-apps/current-work/#boolean-attribute
If you are using something like jQuery's .prop('readonly', true) function, you'll end up needing [readonly], whereas if you are using .attr("readonly", "readonly") then you'll need [readonly="readonly"].
Correction:
You only need to use input[readonly]. Including input[readonly="readonly"] is redundant. See https://stackoverflow.com/a/19645203/1766230

There are a few ways to do this.
The first is the most widely used. It works on all major browsers.
input[readonly] {
background-color: #dddddd;
}
While the one above will select all inputs with readonly attached, this one below will select only what you desire. Make sure to replace demo with whatever input type you want.
input[type="demo"]:read-only {
background-color: #dddddd;
}
This is an alternate to the first, but it's not used a whole lot:
input:read-only {
background-color: #dddddd;
}
The :read-only selector is supported in Chrome, Opera, and Safari. Firefox uses :-moz-read-only. IE doesn't support the :read-only selector.
You can also use input[readonly="readonly"], but this is pretty much the same as input[readonly], from my experience.

input[readonly], input:read-only {
/* styling info here */
}
Shoud cover all the cases for a readonly input field...

capitalize the first letter of Only
input[readOnly] {
background: red !important;
}
<input type="text" name="country" value="China" readonly="readonly" />

If you select the input by the id and then add the input[readonly="readonly"] tag in the css, something like:
#inputID input[readonly="readonly"] {
background-color: #000000;
}
That will not work. You have to select a parent class or id an then the input. Something like:
.parentClass, #parentID input[readonly="readonly"] {
background-color: #000000;
}
My 2 cents while waiting for new tickets at work :D

Use the following to work in all browsers:
var readOnlyAttr = $('.textBoxClass').attr('readonly');
if (typeof readOnlyAttr !== 'undefined' && readOnlyAttr !== false) {
$('.textBoxClass').addClass('locked');
}

Related

CSS: Hide date mm/dd/yyyy placeholder on print

So basically what I want to do is make it so the default placeholder of an input type of date is hidden or transparent when the page is being printed. The trick is that it should still display a valid date when a user inputs one.
There are several things I have already tried, however they are either outdated and do not work with current versions of Chrome or also hide a valid date as well.
I've tried this one (Robin's answer):
Remove default text/placeholder present in html5 input element of type=date
But it hides valid dates when using it inside:
#media print {}
I would like for this placeholder to be missing when printing so that if I wanted to print an empty form, the mm/dd/yyyy won't be in the way. For now I have to temporarily make it transparent if I need to print one off.
Is this possible at all in? Also wondering about changing the placeholder's color to be gray like text input placeholders, but change to black upon entering a valid date.
Thanks.
#media print {
::-webkit-input-placeholder {
color: transparent;
}
:-moz-placeholder {
color: transparent;
}
::-moz-placeholder {
color: transparent;
}
:-ms-input-placeholder {
color: transparent;
}
}
It's a pure workaround, but I had the same issue and this was the simplest route:
function RemoveClass(el, target_class) {
el.classList.remove(target_class);
}
.test {
color: rgba(0,0,0,0);
}
<input type="date" class="test" onclick="RemoveClass(this,'test');">

How can I select every other element that does not have a specific class?

I have a list of <div>s. Each <div> has class zebra. Until now I've used the following to stripe the list:
.zebra:nth-child(2n) { /* colors */ }
Now I'm implementing a filtering feature, such that some of these <div>s will have a class hidden. I tried updating my css to
.zebra:not(.hidden):nth-child(2n) { /* colors */ }
But that had no effect. What am I missing? How can I combine these selectors so that only the showing .zebra <div>s are considered in the :nth-child(2n)?
Here's a fiddle of what I'm describing.
UPDATE:
there is an unknown number of .hidden elements, and an unknown total number of elements. (the list is data-driven, not static).
I'd really rather not do any of:
run a javascript every time a filter control is touched, just to re-color the showing list items.
remove an element entirely when it's hiding. this makes re-adding it non-trivial (afaict).
Instead of removing the element as Justin suggested, you could replace it with an element of a different tag. We could use details, for example:
var placemarker = document.createElement("details");
node.parentNode.replaceChild(placemarker, node);
placemarker.appendChild(node);
Then, instead of using :nth-child, use :nth-of-type.
details { display:none; }
div.zebra:nth-of-type(2n) { /* colors */ }
Unhiding the element can then be done with:
placemarker.parentNode.replaceChild(placemarker.firstChild);
See this static example.
if you don't mind delving into jquery..
$('#yourHiddenElement').remove();
will remove it so that your css shades alternate.
http://jsfiddle.net/NYvcv/1/
I would suggest using this instead of applying the class 'hidden' to the element you want to hide.
If you know there will be a limited number of .hidden items, you can do something like this:
.zebra2:nth-child(2n) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2:nth-child(2n) {
background: inherit;
}
.zebra2.hidden ~ .zebra2:nth-child(2n+1) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2.hidden ~ .zebra2:nth-child(2n) {
background: lightgrey;
}
.zebra2.hidden ~ .zebra2.hidden ~ .zebra2:nth-child(2n+1) {
background: inherit;
}
And so on. This particular example breaks if there are more than 2 hidden items.
​
One possible solution:
use jQuery to change the .hidden element's type to, say, <li>. Use :nth-of-type instead of :nth-child.
http://jsfiddle.net/Nb68T/1/

bgcolor attribute

Havin a table with kind of
<tr bgcolor="#aacbdd">
And I use reset.css which says
...td { background: transparent; ....
And this rule removes all backgrounds set in bgcolor attribute.
But I can't just refuse using reset.css
And I can't change HTML (there are tons of plain HTML in the site like this)
Goal is to save these bgcolor backgrounds.
I tried
.ololo tr
{
background: inherit;
}
But no use. How do I?
If you only have a few colors, you can use an attribute selector:
[bgcolor="#aacbdd"] {
background: #aacbdd;
}
[bgcolor="#c73cab"] {
background: #c73cab;
}
Here's the fiddle: http://jsfiddle.net/JN3wW/
If you have many many different colors, this can get unwieldy. I'd advise you to rely on JavaScript for that. Here's an example using jQuery:
$('tr[bgcolor]').css('background-color', function () {
return $.attr(this, 'bgcolor');
});
Here's the fiddle: http://jsfiddle.net/JN3wW/4/
You're using a CSS/Stylesheet reset, and in stylesheets, the latest definition will be used.
So try setting the style property of the tr rather than the element attribute.
<tr style="background-color:#aacbdd;">

Delay HTML5 :invalid pseudo-class until the first event

I recently discovered that the :invalid pseudo-class applies to required form elements as soon as the page loads. For example, if you have this code:
<style>
input:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" required />
Then your page will load with an empty pink input element on it. Having validation built in to HTML5 is great, but I don't think most users expect the form to validate before they've had a chance to enter any values at all. Is there any way to delay the application of the pseudo-class until the first event affecting that element (form submit, blur, change, whatever's appropriate)? Is it possible to do this without JavaScript?
http://www.alistapart.com/articles/forward-thinking-form-validation/
Since we only want to denote that a field is invalid once it has
focus, we use the focus pseudo-class to trigger the invalid styling.
(Naturally, flagging all required fields as invalid from the start
would be a poor design choice.)
Following this logic, your code would look something like this...
<style>
input:focus:required:invalid {background-color: pink; color: white;}
input:required:valid {background-color: white; color: black; }
</style>
Created a fiddle here: http://jsfiddle.net/tbERP/
As you'd guess, and as you'll see from the fiddle, this technique only shows the validation styling when the element has focus. As soon as you move focus off, the styling is dropped, regardless of whether it is valid or not. Not ideal by any means.
These answers are out of date. Now you can do this by checking for a placeholder pseudo-class with CSS.
input:not(:placeholder-shown):invalid {
background-color: salmon;
}
form:invalid button {
background-color: salmon;
pointer-events: none;
}
<form>
<input type="email" placeholder="me#example.com" required>
<button type="submit">Submit</button>
</form>
It starts with a normal background and turns pink as you enter you incomplete email address into it.
This is not possible in pure CSS, but can be done with JavaScript. This is a jQuery example:
// use $.fn.one here to fire the event only once.
$(':required').one('blur keydown', function() {
console.log('touched', this);
$(this).addClass('touched');
});
/**
* All required inputs initially are yellow.
*/
:required {
background-color: lightyellow;
}
/**
* If a required input has been touched and is valid, it should be white.
*/
.touched:required:valid {
background-color: white;
}
/**
* If a required input has been touched and is invalid, it should be pink.
*/
.touched:required:invalid {
background-color: pink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<label>
Name:
<input type="text" required> *required
</label>
</p>
<p>
<label>Age:
<input type="text">
</label>
</p>
This is a VanillaJS (no jQuery) version of kzh's answer
{
let f = function() {
this.classList.add('touched')
}
document
.querySelectorAll('input')
.forEach((e) => {
e.addEventListener('blur', f, false)
e.addEventListener('keydown', f, false)
})
}
/**
* All required inputs initially are yellow.
*/
:required {
background-color: lightyellow;
}
/**
* If a required input has been touched and is valid, it should be white.
*/
.touched:required:valid {
background-color: white;
}
/**
* If a required input has been touched and is invalid, it should be pink.
*/
.touched:required:invalid {
background-color: pink;
}
<p><label>
Name:
<input type="text" required> *required
</label></p>
<p><label>Age:
<input type="text">
</label></p>
Mozilla takes care of this with its own :-moz-ui-invalid pseudoclass that only applies to forms after they've been interacted with. MDN does not recommend using this due to a lack of support. However, you can modify it for Firefox.
There's a level 4 spec for a :user-invalid spec on the horizon that will offer similar behavior.
I created a small shim to deal with this in my codebase. I just start off with my <form/> element having the novalidate property along with a data-validate-on="blur" attribute. This watches for the first event of that type. This way you can still use the native :invalid css selectors for the form styling.
$(function () {
$('[data-validate-on]').each(function () {
var $form = $(this);
var event_name = $form.data('validate-on');
$form.one(event_name, ':input', function (event) {
$form.removeAttr('novalidate');
});
});
});
There is a html5 invalid event that fires on form elements before the submit event occurs for each element that does not pass checkValidity. You can use this event to apply a class for example to the surrounding form and display :invalid styles only after this event occurs.
$("form input, form select, form textarea").on("invalid", function() {
$(this).closest('form').addClass('invalid');
});
Your CSS would then look something like this:
:invalid { box-shadow: none; }
.invalid input:invalid,
.invalid textarea:invalid,
.invalid select:invalid { border: 1px solid #A90909 !important; background-color: #EEC2C2; }
The first line removes the default styling, so form elements look neutral at page load. As soon as the invalid event fires (when a user tries to submit the form), the elements are visibly rendered invalid.
You could make it so that only elements that have a certain class on them and are required, are pink. Add an event handler to each required element that adds that class when you leave the element.
Something like:
<style>
input.touched:invalid { background-color: pink; color: white; }
input.touched:valid { background-color: white; color: black; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function() {
var required = document.querySelectorAll('input:required');
for (var i = 0; i < required.length; ++i) {
(function(elem) {
function removeClass(name) {
if (elem.classList) elem.classList.remove(name);
else
elem.className = elem.className.replace(
RegExp('(^|\\s)\\s*' + name + '(?:\\s+|$)'),
function (match, leading) {return leading;}
);
}
function addClass(name) {
removeClass(name);
if (elem.classList) elem.classList.add(name);
else elem.className += ' ' + name;
}
// If you require a class, and you use JS to add it, you end up
// not showing pink at all if JS is disabled.
// One workaround is to have the class on all your elements anyway,
// and remove it when you set up proper validation.
// The main problem with that is that without JS, you see what you're
// already seeing, and stuff looks hideous.
// Unfortunately, you kinda have to pick one or the other.
// Let non-blank elements stay "touched", if they are already,
// so other stuff can make the element :invalid if need be
if (elem.value == '') addClass('touched');
elem.addEventListener('blur', function() {
addClass('touched');
});
// Oh, and when the form submits, they need to know about everything
if (elem.form) {
elem.form.addEventListener('submit', function() {
addClass('touched');
});
};
})(required[i]);
}
});
</script>
And of course, it won't work as is in IE8 or below, as (a) DOMContentLoaded is relatively new and wasn't standard when IE8 came out, (b) IE8 uses attachEvent rather than the DOM-standard addEventListener, and (c) IE8 isn't going to care about :required anyway, as it doesn't technically support HTML 5.
While using HTML5 form validation, try to use the browser to detect for invalid submissions/fields, rather than re-inventing the wheel.
Listen for the invalid event to add a class of 'invalid' to your form. With the 'invalid' class added, you can go to town with styling your form using CSS3 :pseudo selectors.
For example:
// where myformid is the ID of your form
var myForm = document.forms.myformid;
var checkCustomValidity = function(field, msg) {
if('setCustomValidity' in field) {
field.setCustomValidity(msg);
} else {
field.validationMessage = msg;
}
};
var validateForm = function() {
// here, we're testing the field with an ID of 'name'
checkCustomValidity(myForm.name, '');
if(myForm.name.value.length < 4) {
checkCustomValidity(
// alerts fields error message response
myForm.name, 'Please enter a valid Full Name, here.'
);
}
};
/* here, we are handling your question above, by adding an invalid
class to the form if it returns invalid. Below, you'll notice
our attached listener for a form state of invalid */
var styleInvalidForm = function() {
myForm.className = myForm.className += ' invalid';
}
myForm.addEventListener('input', validateForm, false);
myForm.addEventListener('keyup', validateForm, false);
myForm.addEventListener('invalid', styleInvalidForm, true);
Now, simply style your form as you see fit based on the 'invalid' class we've attached.
For example:
form.invalid input:invalid,
form.invalid textarea:invalid {
background: rgba(255, 0, 0, .05);
border-color: #ff6d6d;
-webkit-box-shadow: 0 0 6px rgba(255, 0, 0, .35);
box-shadow: 0 0 6px rgba(255, 0, 0, .35);
}
A good way is to abstract :invalid, :valid with a CSS classes and then some JavaScript to check if the input field was focused or not.
CSS:
input.dirty:invalid{ color: red; }
input.dirty:valid{ color: green; }
JS:
// Function to add class to target element
function makeDirty(e){
e.target.classList.toggle('dirty');
}
// get form inputs
var inputs = document.forms[0].elements;
// bind events to all inputs
for(let input of inputs){
input.addEventListener('invalid', makeDirty);
input.addEventListener('blur', makeDirty);
input.addEventListener('valid', makeDirty);
}
DEMO
Following on from agouseh's idea, you can have a bit of javascript to tell when the submit button has been focussed, and have validation show up at that time.
The javascript will add a class (eg. submit-focussed) to the form field when the submit button is focussed or clicked, which then allows the CSS to style invalid inputs.
This follows the best practice of showing validation feedback after the user has finished filling in the fields, as according to research there is no additional benefit to showing it during the process.
document
.querySelector('input[type=submit]')
.onfocus = function() {
this
.closest('form')
.classList
.add('submit-focussed');
};
form.submit-focussed input:invalid {
border: thin solid red;
}
<form>
<label>Email <input type="email" required="" /></label>
<input type="submit" />
</form>
jQuery alternative
(function($) {
$('input[type=submit]').on('focus', function() {
$(this)
.parent('form')
.addClass('submit-focussed');
});
})(jQuery); /* WordPress compatible */
Here is my method to avoid the default styling of any unfocused input as invalid, you just have to add a simple js command onFocus to let the webpage to identify focused and unfocused inputs, so all the input will not appear in the style of invalid at first place.
<style>
input.focused:required:invalid { background-color: pink; color: white; }
input:valid { background-color: white; color: black; }
</style>
…
<input name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required />
Try it yourself below:
input.focused:required:invalid {
background-color: pink;
color: white;
}
input:required:valid {
background-color: darkseagreen;
color: black;
}
<label>At least 1 charater:</label><br />
<input type="text" name="foo" class="notfocused" onFocus="document.activeElement.className='focused';" required />
I can't comment, but to go with #Carl's very useful answer regarding using :not(:placeholder-shown). As another comment mentioned, this will still show the invalid state if you have NO placeholder (as some form designs call for).
To solve this, simply add an empty placeholder like so
<input type="text" name="username" placeholder=" " required>
Then your CSS, something like
:not(:placeholder-shown):invalid{ background-color: #ff000038; }
Worked for me!

Webkit (Chrome/Safari) does not update display when custom attribute selected is changed

Working example: http://jsfiddle.net/JVVcA/
HTML:
<fieldset id="data-page">
<legend>data-page</legend>
<button rel="page1">Highlight page one</button>
<button rel="page2">Highlight page two</button>
<div data-page="page1">
<h1 id="page1">Page one</h1>
<h1 id="page2">Page two</h1>
</div>
</fieldset>
<fieldset id="class">
<legend>class</legend>
<button rel="page3">Highlight page three</button>
<button rel="page4">Highlight page four</button>
<div class="page3">
<h1 id="page3">Page three</h1>
<h1 id="page4">Page four</h1>
</div>
</fieldset>
CSS:
fieldset { border: 1px solid #aaa; padding: 5px; }
h1 { background-color: white; }
div[data-page="page1"] h1#page1 { background-color: pink; }
div[data-page="page2"] h1#page2 { background-color: pink; }
div.page3 h1#page3 { background-color: cyan; }
div.page4 h1#page4 { background-color: cyan; }
JS:
$('#data-page button').click(function(){
var rel = $(this).attr('rel');
$(this).siblings("div").attr('data-page', rel);
});
$('#class button').click(function(){
var rel = $(this).attr('rel');
$(this).siblings("div").attr('class', rel);
});
Initial load:
After clicking "Highlight page two" and "Highlight page four" in Webkit (specifically, Google Chrome stable Windows 7):
After doing the same in Firefox:
As you can see, the data-page selector works fine on the initial rendering of the of the page, but when the DOM is manipulated on the fly, styles defined by the [data-page="???"] CSS selector are not affected accordingly. Compare this to the situation with the class selectors. When classes are changed on the fly, the styles change as expected.
A possibly related note is that I've encountered cases while using this attribute selector in conjunction with CSS transitions where a similar lack of responsiveness happens, but on those cases, clicking elsewhere on the page, waving your mouse around, or just waiting for a bit eventually results in the expected change going through.
So is there a way around this other than to just throw up your hands and not use data-page-style attributes?
It's the same issue that's applied for the ~ or multiple + selectors and pseudo-classes in webkit: this kind of selectors are rendered only once and the last time I checked the relevant bug reports in webkit's tracker, they stated that it works like intended.
But, some people had found the fix, but it's really is overhead: to add always-reflowing property to body, so it's must be added only to those elements, where something changes, the divs inside field sets for your example.
So, there is a fixed fiddle: http://jsfiddle.net/JVVcA/2/
And these are the styles for fixing such problems:
/* The `fixing` animation */
#-webkit-keyframes bugfix { from { padding: 0; } to { padding: 0; } }
.anElementToFix { -webkit-animation: bugfix infinite 1s; }
Note that you must add the fix to the element whose attribute is can be changed, not the targeted by selector elements.
My version of workaround.
$('#data-page button').click(function(){
var rel = $(this).attr('rel');
var my_div = $(this).siblings("div");
my_div.attr('data-page', rel);
var my_html = my_div.html();
my_div.html(my_html);
});
$('#class button').click(function(){
var rel = $(this).attr('rel');
$(this).siblings("div").attr('class', rel);
});
Running an animation seems overly expensive.
Thanks to Zoltan Olah, I found a much more elegant, concise, and efficient workaround.
Simple toggle a nonsense class on the body. This will cause contained selectors to be re-evaluated.
You don't even have to define this class in CSS. Just applying it forces Safari to hunt through the page re-evaluating things.
Every time you change the attribute in question, toggle this class on or off to force the re-evaluation.
// change some attribute
$(".blah").attr("state", "otherState"); // example of changing an attribute (your app will be different)
$('body').toggleClass('zoltan'); // THIS IS THE LINE YOU MUST ADD EVERY TIME YOU CHANGE THE ATTRIBUTE