Is it possible to get the browser's default (or themed, assuming there are browser themes? I've never looked) text selection color?
Background
I'm trying to make an <input type="date" /> act like it has a placeholder attribute, like the HTML5 <input type="text" /> does. In case it matters, I'm using Bootstrap.
So far, I've got
CSS
/* allow date inputs to have placeholders */
/* display placeholder text */
input[type="date"].emptyDate:before {
content: attr(placeholder);
color: #999;
}
/* hide default mm/dd/yyyy text when empty value and not in focus */
input[type=date].emptyDate:not(:focus) {
color: transparent;
}
/* hide default mm/dd/yyyy text when empty value, not in focus, and
selected (ctrl + a) */
input[type="date"].emptyDate::selection:not(:focus) {
color: transparent;
background-color: lightblue;
}
/* hide placeholder text when empty value, but in focus */
input[type="date"].emptyDate:focus:before {
content: "";
}
Javascript
function setEmptyDateInputClass(input) {
if ($(input).val()) {
$(input).removeClass("emptyDate");
} else {
$(input).addClass("emptyDate");
}
}
$(document).ready(function () {
$.each($("input[type=date]"), function (i, input) {
// set initial class
setEmptyDateInputClass(input);
// set class on value change
$(input).change(function () { setEmptyDateInputClass(this);});
});
});
Issues
I'm having two issues. The first, and the one I'm asking in this question (I'll post another question if everyone obeys the rules and no one posts answers to multiple questions) is, is there a way to get the browser's default (or themed) selection background color so that, either with CSS or manually with Javascript, the lightblue isn't static? (Also, light blue isn't the right color, but that's just a matter of a screenshot and mspaint.)
input[type="date"].emptyDate::selection:not(:focus) {
background-color: lightblue;
}
My second, bonus issue is, I'm having issues selecting :before::selection in order to set the background color of selected ::before content.
/* always active when .emptyDate */
input[type="date"].emptyDate::selection:before {
background-color: lightblue;
}
/* never active */
input[type="date"].emptyDate:before::selection {
background-color: lightblue;
}
You can use specificity on ::selection like so:
CSS
.red::selection {
background-color: red;
color: #fff;
}
.green::selection{
background-color:green;
color:#fff;
}
HTML
<span class="red">I am highlighted in red, </span>
<span class="green">and I am highlighted in green,</span>
<span class="">and I am highlighted as per browser default.</span>
Example: http://www.bootply.com/KEEvWSlP0F
Related
I currently have a toggle that when clicked adds/removes a class to the html tag.
I'd like to update this so if you click after the original class is added the class is changed to .new-mode rather than removing the current class and the html tag being class-less. If the link is clicked again, it will then return to the default state.
So in essence it's got 3 states:
No class (default / on load)
Class One added (on 1st click)
Class One removed, Class Two added (on 2nd click)
Then on the next click it would return to the default state without a class. So essentially just cycling through 2 classes on click. You can see I have the 1st toggle working in my example - but I'm unsure how to target the next click(s) and I'd really appreciate some help.
const html = document.querySelector('html');
const button = document.querySelector('.contrast__link');
button.addEventListener('click', e => {
e.preventDefault();
html.classList.toggle('dark-mode');
});
html { background: white; color: black; }
.dark-mode { background: black; color: white;}
.new-mode { background: blue; color: white;}
<p class="contrast__link">Click here</p>
Check what the current state is and handle the transition to the next state. Since you have a reference to the html element, you can use its classList property to see which classes are currently applied to it.
The return value is not an array, it's a DOMTokenList, so be sure to use DOMTokenList.contains() instead of Array#includes. The collection also supports adding, removing, and toggling one or more classes.
The simplest way to check and change the state is an if-else chain:
const html = document.querySelector('html');
const button = document.querySelector('.contrast__link');
button.addEventListener('click', e => {
e.preventDefault();
if (html.classList.contains('dark-mode')) {
html.classList.remove('dark-mode');
html.classList.add('new-mode');
}
else if (html.classList.contains('new-mode')) {
html.classList.remove('new-mode');
}
else {
html.classList.add('dark-mode');
}
});
html { background: white; color: black; }
.dark-mode { background: black; color: white;}
.new-mode { background: blue; color: white;}
<p class="contrast__link">Click here</p>
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 months ago.
Improve this question
1. Original Question & First Bounty
Given a very basic color scheme.
One that allows the website user to set a desired theme from a predefined set of CSS root variable definitions.
Is there an easy way to let the browser remember the theme, it set by the user, so that the user's input is carried over to the next pages? Thus eliminating the need for setting the color scheme on every new page!
const setTheme = theme => document.documentElement.className = theme;
document.getElementById('scheme').addEventListener('click', ({target}) => {
setTheme(target.getAttribute('id'));
});
html{margin: 10px}
#scheme p{ /* User Interface */
display: inline-block;
text-decoration: underline;
}#scheme p:hover{cursor: pointer}
:root{ /* Default Theme */
--bgr: #eee;
--txt: #000;
}
:root.light {
--bgr: #ddc;
--txt: #466;
}
:root.dark {
--bgr: #222;
--txt: #A75;
}
:root.blue{
--bgr: #246;
--txt: #eec;
}
body { /* Have something to test */
background: var(--bgr);
color: var(--txt);
}
<div id="scheme">
<p id="light">Light</p>
<p id="dark">Dark</p>
<p id="blue">Blue</p>
<p id="etc">Etc</p>
</div>
<h1>Click on a theme to change the color scheme!</h1>
2. Updated Precision & Second Bounty
Attention to the Original Question and Improvements Needed
The current two answers have some problems from the point of view of the original question: one answer has A)diverged away from the css root: {}/* Default Theme */ by introducing root.default{} and B) has implemented automatic theme selection with "light"/"dark" an and added "auto" theme, which though awesome for some, is the opposite of what is asked in the question: a simple manual user choice, overruling just one "unset" root: {} default theme.
The other answer thought nice and basic C) necessitates manually setting the optional CSS theme names in an JavaScript array, making it prone to future errors and would be nice not need setting because all manual theme options are consistently named like :root.themename{}. D) Also this solution causes a second or so delay when setting themes in mobile iOS devices!?
2nd Bounty goes to new answers that check the most of these points:
Stick to the original questions root:{} as the only default (unset theme). *1)
Nothing beyond the basics, no automatic theme selection please.
Do not necessitate css theme names in JavaScript code.
Allow SVG boxes as buttons for more design flexibility. *2)
*1) The reason why I want root: {} as default theme, is because I would like to set CSS Filters like saturation and grayscale on the themes that impact the entire page, images, logos, everything!
*2) Simpler cleaner html with svg buttons for setting the themes. In this future third and last bounty, plain SVG boxes (with one or more colours) serve as buttons for setting the themes! How awesome would that be?! Wordless, Timeless! See snippet below.
:root{ /* Default Theme, if no theme is manually selected by user */
--bgr: #eee;
--txt: #000;
--flt: none;
}
:root.blackwhite{
--bgr: #fff;
--txt: #000;
--flt: contrast(100%) grayscale(100%);
}
:root.sepia {
--bgr: lightblue;
--txt: red;
--flt: sepia(75%);
}
:root.holiday{
--bgr: #fba;
--txt: #269;
--flt: blur(.25px) saturate(4);
}
:root.moody{
--bgr: green;
--txt: yellow;
--flt: drop-shadow(16px 16px 20px yellow) blur(1px);
}
html { /* Have something to test */
background: var(--bgr);
color: var(--txt);
filter: var(--flt); /* important filter that affects everything */
}
h1{
background: var(--bgr);
color: var(--txt);
}
theme{ /* html element div that contains only SVG graphics */
display: flex;
flex-direction: row;
}
<!--I prefer a custom more logical `<theme>` over an equally
meanigless <div id="theme"> as container, since both do not
carry any semantic meaning. But, if you prefer a standard div,
then thats fine! Just explain why thats better. Thanks!-->
<theme>
<svg id="blackwhite"><rect width="100" height="50" /></svg>
<svg id="sepia" ><rect width="100" height="50" /></svg>
<svg id="holiday" ><rect width="100" height="50" /></svg>
<svg id="moody" ><rect width="100" height="50" /></svg>
</theme>
<h1>Click on a theme to change the color scheme!</h1>
<p>Some Paragraph texts.</p>
<img src="\clouds.jpg" alt="clouds"/>
3. Updated User Interface Feedback & Third Bounty
Show the user which theme he has manually clicked on.
Add a class .chosentheme to the svg element that is currently chosen or active, so that the user can see which one of the theme buttons is currently active/chosen/selected!
<theme id="scheme">
<svg id="blackwhite"><rect/></svg>
<svg id="midnight"><rect/></svg>
<svg id="beach"><rect/></svg>
<svg ><rect/></svg><!-- currently works as a (dummy) button to activate the :root{} Default Theme -->
</theme>
If no svg is selected yet, or if the memory is empty, then the last svg could be automatically selected via CSS or via setting an exception for this one id in the code like "defaulttheme", <svg id="defaulttheme">, which already works as a (dummy) button to load the default theme :root{}.
(It's okay if by default, when the memory is empty, nothing is selected, even not the last default theme svg).
Then, if any of the svg's is clicked or if a theme is loaded from memory, then the .chosentheme styling should be applied via JavaScript dynamically, and added to that svg element's list of class names, letting the user know that he has manually clicked on that theme or that that theme is currently already loaded and showing.
theme svg.chosentheme { border: 1px solid black }
/* Sets a border around the currently activated theme */
/* Because someone clicked on it or because its stored in memory */
Try this simple resolve: to save, load and select a theme from local storage.
Local Storage doesn't working in snippets or sandboxes.
The localStorage read-only property of the window interface allows you to access a Storage object for the Document's origin; the stored data is saved across browser sessions. MDN documentation
JS
// Select class name as in CSS file
const CLASS_NAME = 'chosentheme';
const scheme = document.getElementById('scheme');
// Creating an array of SVG elements
const svgElementsArray = [...scheme.querySelectorAll('svg')];
// Creating a color theme array using the SVG ID attribute
const themeNameArray = svgElementsArray.map(theme => theme.id);
// Get html node (html tag)
const htmlNode = document.documentElement;
// Get color (value) from local storage
const getLocalStorageTheme = localStorage.getItem('theme');
const setTheme = theme => {
// Set class to html node
htmlNode.className = theme;
// Set theme color to local storage
localStorage.setItem('theme', theme);
svgElementsArray.forEach(svg => {
// If we click on the svg and it has a class, do nothing
if (svg.id === theme && svg.classList.contains(CLASS_NAME)) return;
// Check, if svg has the same ID and if it doesn't have a class,
// then we adding class and removing from another svg
if (svg.id === theme && !svg.classList.contains(CLASS_NAME)) {
svg.classList.add(CLASS_NAME);
} else {
svg.classList.remove(CLASS_NAME);
}
});
};
// Find current theme color (value) from array
const findThemeName = themeNameArray.find(theme => theme === getLocalStorageTheme);
// If local storage empty
if (getLocalStorageTheme) {
// Set loaded theme
setTheme(findThemeName);
} else {
// Find last svg and set the class (focus)
svgElementsArray.at(-1).classList.add(CLASS_NAME);
}
document.getElementById('scheme').addEventListener('click', ({ target }) => {
// Getting ID from an attribute
const id = target.getAttribute('id');
// Find current theme color (value) from array
const findThemeName = themeNameArray.find(theme => theme === id);
setTheme(findThemeName);
});
We also need to prevent selection of child elements inside the button (SVG) and to select exactly the button with ID attribute.
CSS
theme svg > * {
pointer-events: none;
}
theme svg {
/* to prevent small shifts,
when adding the chosentheme class */
border: 1px solid transparent;
}
theme svg.chosentheme {
border-color: black;
}
To prevent the webpage from flickering (blinking) while is loading, place this snippent at the top of the head tag. (prevent dark themes from flickering on load)
HTML
<head>
<script>
function getUserPreference() {
if(window.localStorage.getItem('theme')) {
return window.localStorage.getItem('theme')
}
}
document.documentElement.dataset.theme = getUserPreference();
</script>
....
</head>
// Select class name as in CSS file
const CLASS_NAME = 'chosentheme';
const scheme = document.getElementById('scheme');
// Creating an array of SVG elements
const svgElementsArray = [...scheme.querySelectorAll('svg')];
// Creating a color theme array using the SVG ID attribute
const themeNameArray = svgElementsArray.map(theme => theme.id);
// Get html node (html tag)
const htmlNode = document.documentElement;
// Get color (value) from local storage
const getLocalStorageTheme = localStorage.getItem('theme');
const setTheme = theme => {
// Set class to html node
htmlNode.className = theme;
// Set theme color to local storage
localStorage.setItem('theme', theme);
svgElementsArray.forEach(svg => {
// If we click on the svg and it has a class, do nothing
if (svg.id === theme && svg.classList.contains(CLASS_NAME)) return;
// Check, if svg has the same ID and if it doesn't have a class,
// then we adding class and removing from another svg
if (svg.id === theme && !svg.classList.contains(CLASS_NAME)) {
svg.classList.add(CLASS_NAME);
} else {
svg.classList.remove(CLASS_NAME);
}
});
};
// Find current theme color (value) from array
const findThemeName = themeNameArray.find(theme => theme === getLocalStorageTheme);
// If local storage empty
if (getLocalStorageTheme) {
// Set loaded theme
setTheme(findThemeName);
} else {
// Find last svg and set the class (focus)
svgElementsArray.at(-1).classList.add(CLASS_NAME);
}
document.getElementById('scheme').addEventListener('click', ({
target
}) => {
// Getting ID from an attribute
const id = target.getAttribute('id');
// Find current theme color (value) from array
const findThemeName = themeNameArray.find(theme => theme === id);
setTheme(findThemeName);
});
:root {
/* Default Theme, if no theme is manually selected by user */
--bgr: #eee;
--txt: #000;
--flt: none;
}
:root.blackwhite {
--bgr: #fff;
--txt: #000;
--flt: contrast(100%) grayscale(100%);
}
:root.midnight {
--bgr: lightblue;
--txt: red;
--flt: sepia(75%);
}
:root.beach {
--bgr: #fba;
--txt: #269;
--flt: blur(0.25px) saturate(4);
}
/* :root.moody {
--bgr: green;
--txt: yellow;
--flt: drop-shadow(16px 16px 20px yellow) blur(1px);
} */
html {
/* Have something to test */
background: var(--bgr);
color: var(--txt);
filter: var(--flt);
/* important filter that affects everything */
}
h1 {
background: var(--bgr);
color: var(--txt);
}
theme {
/* html element div that contains only SVG graphics */
display: flex;
flex-direction: row;
}
theme svg > * {
/* prevent selection */
pointer-events: none;
}
theme svg {
/* to prevent small shifts,
when adding a focus class */
border: 1px solid transparent;
}
theme svg.chosentheme {
border-color: black;
}
<theme id="scheme">
<svg id="blackwhite"><rect /></svg>
<svg id="midnight"><rect /></svg>
<svg id="beach"><rect /></svg>
<svg id="defaulttheme"><rect /></svg>
</theme>
<h1>Click on a theme to change the color scheme!</h1>
<p>Some Paragraph texts.</p>
There are several ways to to persist data in the browser between page loads:
cookies
localStorage
sessionStorage
IndexedDB
I suggest using localStorage. Here is a very detailed comparison of the different methods.
update:
localStorage never expires. The user may manually delete/reset the localStorage via the browser settings/dev console.
You can control the expiration of values in localStorage by storing the expiration timestamp with the value and checking the timestamp each time the value is retrieved. (If you just want the values to expire after a page session, use sessionStorage.)
amplify.store is a wrapper around the browser storage API's. It lets you set an optional expiration time.
Using matchMedia and prefers-color-scheme you can apply a default theme based on the user's system-wide preference. This will adjust automatically if the user has enabled auto-switching based on the time of day or through the light sensor on their device.
Then, if they choose to override this, save their selection in localStorage. This preference will remain until the user clears the storage for your origin.
<!DOCTYPE html>
<head>
<title> Theme Selector Test </title>
<style>
:root.default { --bgr: #eee; --txt: #000; }
:root.light { --bgr: #ddc; --txt: #446; }
:root.dark { --bgr: #222; --txt: #a75; }
:root.blue { --bgr: #246; --txt: #eec; }
body { background: var(--bgr); color: var(--txt); margin: 1.5rem; }
</style>
<script>
let prefersDark = matchMedia('(prefers-color-scheme: dark)');
prefersDark.addEventListener('change', event => loadTheme());
function setTheme(theme) {
if (theme == 'auto') {
localStorage.removeItem('theme');
loadTheme(null);
} else {
localStorage.setItem('theme', theme);
applyTheme(theme);
}
}
function loadTheme(theme) {
theme = localStorage.getItem('theme');
theme ??= (prefersDark.matches) ? 'dark' : 'default';
applyTheme(theme);
}
function applyTheme(theme) {
document.documentElement.className = theme;
}
window.setTheme = setTheme;
loadTheme();
</script>
</head>
<body>
<h1> Select a theme to change the color scheme! </h1>
<select id="scheme">
<option value="auto">Auto</option>
<option value="default">Default</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="blue">Blue</option>
</select>
<script>
let selector = document.getElementById('scheme');
selector.value = localStorage.getItem('theme') || 'auto';
selector.addEventListener('click', event => window.setTheme(selector.value));
</script>
</body>
See this answer for instructions on how to simulate the system-wide preference for testing purposes.
As #Anton mentioned, localStorage doesn't work in snippets here on Stack Overflow due to sandboxing so instead I've written this as a full page example to demonstrate the best way to implement it in a real-world environment.
I have also published an ES Module version of this. Implementing the inline version as demonstrated in this post is better for performance but the module version is better if you want to avoid polluting the global scope.
I've used a <select> element in the example since this is probably how most user's who find this in the future will likely want to use it. To display the options like you have shown in your question you can implement as demonstrated below. Note that I've replaced the <p> tags with <button> for better accessibility. I've also added an extra check in the click handler to avoid setTheme from being called if the background area of the container <div> is clicked.
In your CSS :
#scheme button {
border: 0;
background: none;
color: inherit;
text-decoration: underline;
cursor: pointer;
}
#scheme button * {
pointer-events: none;
}
In your HTML <body> :
<div id="scheme">
<button id="auto">Auto</button>
<button id="default">Default</button>
<button id="light">Light</button>
<button id="dark">Dark</button>
<button id="blue">Blue</button>
</div>
<h1>Click on a theme to change the color scheme!</h1>
<script>
let selector = document.getElementById('scheme');
selector.addEventListener('click', event => {
if (event.target == selector) { return; }
window.setTheme(event.target.id);
});
</script>
If used inside a form, you'll need to add event.preventDefault(); to the click handler to avoid submitting when the buttons are clicked.
I want to change the view of an object from a JS function depending on any events.
For example, I have a set of forms, including an input form of type text. While it is not completely filled, the color of the frame and font is green, when it is completely filled - red.
At the same time, I want to keep the freedom of the HTML designer and give him the opportunity to set class names arbitrarily. I want to operate at the subclass level.
I set this:
.info.available {
color: green;
border: 1px solid lime;
}
.info.full {
color: red;
border: 1px solid red;
}
And
<input class="info available" type="text" id="info">
I have a function myfunc(obj) that takes a pointer "this" and works with different components of a formset.
How for obj.form.info ... to switch the subclass from "available" to "full" and vice versa? How can I get its current value?
first, specify an input maxlength to know if its is completely filled or not.
<input class="info available" max-length="10" type="text" id="input">
then remove the outline color from your input field when it is clicked or being typed
input.available {
border: 1px solid green;
}
input.full {
border: 1px solid red;
}
input:focus {
outline: none;
}
this is to make .available and .full classes visible. then add an action event to your input field that will listen for every string that is typed. you can do it by:
next in your script tag, create the function that will be fired from your input field
<script>
function myfunc(e) {
let x = document.getElementById('input')
if (x.value.length == 10)
{
x.classList.remove('available')
x.classList.add('full')
}
else {
x.classList.add('available')
x.classList.remove('full')
}
}
</script>
x refers to your input field
x.value.length refers to the length of characters that is in your input field
if x.value.length is equal to your input's maxlength(which we specified as 10), it will replace the class .available by .full and vice versa
you can read the documentation or tutorials here:
https://www.w3schools.com/js/js_events.asp
https://www.w3schools.com/tags/ref_eventattributes.asp
Use maxlength="{maxlen}" for your input.
function myfunc(obj) {
if (obj.value.length >= maxlen) {
obj.classList.remove('available');
obj.classList.add('full');
} else {
obj.classList.add('available');
obj.classList.remove('full');
}
}
I have a button in HTML and I want the user to be able to change the button's text when double clicking.
<button onclick='doStuff()' ondblclick='renameButton()' id='myButton'>Click Me</button>
This is my function in JavaScript:
function renameButton() {
var button = document.getElementById('myButton');
button.setAttribute("contenteditable", true);
}//end renameButton
This function allows me to edit the button:
Issue 1) I cannot add a space when editing the button. The space-bar on my keyboard literally does nothing.
Issue 2) Is it possible to set a white background on the editable text to allow the user to see that it is editable? As far as I know, it is only possible to control the background color of the entire button element, but not the text node.
You need to put a span kind of element to hold the text inside the button if you want to make sure SPACE is fed into the content.
On a button, space is a trigger for button press and hence can't be added in to the text with contenteditable attribute.
See it working here: https://jsfiddle.net/mwwj1jty/2/
HTML
<button onclick='doStuff()' ondblclick='renameButton()' id='myButton'><span id="myspan">Click Me</span></button>
JAVASCRIPT
function renameButton() {
var span = document.getElementById('myspan');
span.setAttribute("contenteditable", true);
span.style.backgroundColor = "red";
}//end renameButton
You could put a span inside the button where the text is, and change the background-color of the span instead as seen here https://jsfiddle.net/msoLg3qb/
HTML
<button ondblclick='renameButton()' id='myButton'><span>Click Me</span></button>
CSS
span {
background-color: white;
}
button {
background-color: green;
}
JAVASCRIPT
var button = document.getElementById('myButton');
function renameButton() {
button.setAttribute("contenteditable", true);
}
Don't use a button element for this, as you can see that there are limitations. When a button is active, pressing the SPACE key initiates a click event. To get around this, use a different element, a span would be perfect here.
I've also added the background color as you asked about.
Lastly, don't use inline HTML event attributes (onclick, etc.). That's an ancient technique that just will not die but has many reasons not to use it. Instead, follow modern standards and use .addEventListener().
// Get a reference to the button
var spn = document.getElementById("myButton");
// Set up your event handlers in JavaScript, not in HTML
spn.addEventListener("click", doStuff);
spn.addEventListener("dblclick", renameButton);
spn.addEventListener("blur", saveName);
function renameButton() {
spn.contentEditable = "true";
spn.classList.add("edit");
}
function saveName(){
spn.contentEditable = "false";
spn.classList.remove("edit");
}
function doStuff(){
}
/* Make span look like a button */
.button {
display:inline-block;
padding:5px 20px;
border:1px solid grey;
background-color:green;
border-radius:2px;
cursor:pointer;
box-shadow:1px 1px 1px grey;
color:white;
user-select:none;
}
/* Make span feel like a button */
.button:active {
box-shadow:-1px -1px 1px white;
}
/* Style to add while content is editible */
.edit {
background-color:white;
color:black;
}
<span id='myButton' class="button">Click Me</span>
I would like to have a text field which has pre appended text which is not modifiable.
So when user tries to add text it starts after the pre text.
Also when the form is submitted it should not pass the pre appended text. Its mainly for display purpose but within the text field. I have attached the image which will clarify my question further. For example I would like to add "$" as pre text in the image below. Any help is greatly appreciated.
Note: the $ is dynamic text and so could not be image.
I've made a fiddle with two solutions, both using CSS.
The first uses a data URI of a PNG that contains a dollar sign for the background image of the text input. The second uses a label containing a dollar sign and shifts it over to be on top of the input (you probably should use a span instead of a label, for accessibility's sake).
HTML:
<input type="text" id="bob" />
<br/>
<label for="fred">$</label><input type="text" id="fred" />
CSS:
#bob {
background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgBAMAAACBVGfHAAAAG1BMVEX///8AAAC/v7/f398/Pz8fHx9/f3+fn59fX19QuZN1AAAAbElEQVQokWNgGFyASRiN7ygYhiKgGCYW6IAs4KgsYCqELCDKLMCehCwQyCyAamhjM5qAiaC4AqpIiaAoqgizuKMQqoAAuwgytxxoiyiSABvQHcwoKgSVBVjEkI1IlEDzCzu6bxnQnY4pQFsAAC/cCbAPkBI2AAAAAElFTkSuQmCC') no-repeat;
background-size: contain;
padding-left: 1.1em;
}
label[for="fred"] {
position: relative;
left: 15px;
z-index: 1000;
font-size: smaller;
}
#fred {
padding-left: 1.2em;
}
Both of these methods are hacky. A JS solution would be more involved, but handle much more nicely (I just don't have time to implement one).
Here's a neat way using background-image
http://jsfiddle.net/dxu2s/1/
HTML:
<label for="RefundAmount">Enter a refund amount: </label>
<input type="text" name="RefundAmount" id="RefundAmount">
CSS:
#RefundAmount {
margin: 0;
padding: 0 0 0 25px;
width: 100px;
height: 25px;
background: #FFF url(http://oi57.tinypic.com/nmncz5.jpg) no-repeat left center;
}
I've also tried using the css psuedo-element :before but it didn't work as input tags doesn't have content in em'.
This is a class i wrote you can use it for free, i didnt test it a lot. if you find a bug let me know
HTML: <input type="text" id="inputA" value="$" />
in script add this Class constructor
//***************************************************************
//-------------------------------------- Class halfEditable_INPUT
//***************************************************************
//-- divides an Input into an non editable area from 0 to index, but not including the index, the rest is editable
//-----------------------------------------------------
//-------- constructor
//-----------------------------------------------------
function halfEditable_INPUT (inputField,index)
{
if (typeof index=="undefined") index=inputField.value.length;
//------------------------------------ PUBLIC Objects, Properties
this.element=inputField;
this.index=index;
//-- a reference to the instance of the halfEditable_INPUT class saved in the html element, to get instance values in DOM events
Object.defineProperty (inputField,"halfEditable_instance",{value:this,writable: false, enumerable:true, configurable:true});
//-- get the value of the input directly
Object.defineProperty (this,"value", {get:this.PRIVATE_getValue,set:this.PRIVATE_setValue});
inputField.addEventListener ("keydown",this.PRIVATE_checkStatus_ONKEYDOWN);
}
//-----------------------------------------------------
//-------- prototype
//-----------------------------------------------------
//------------------------------------ PRIVATE Methods
/* this --- points to the input field
checks if the cursorPosition is in the non Editable area or is at the limit Point
if it is at the limitPoint - dont allow backspace or cursor left
if it is inside allow nothing and move cursorPosition to the limit
reset the Position1 key to index */
halfEditable_INPUT.prototype.PRIVATE_checkStatus_ONKEYDOWN=function (event)
{
var keyCode=event.keyCode;
var index=this.halfEditable_instance.index;
var selectionStart=this.selectionStart, selectionEnd=this.selectionEnd;
if (keyCode==36) //-- position1 key
{
event.preventDefault();
this.setSelectionRange (index,index);
return;
}
if (selectionStart<index)
{
if (selectionEnd>index) this.setSelectionRange (index,selectionEnd);
else this.setSelectionRange (index,index);
}
else if (selectionStart==index) {if (keyCode==8 || keyCode==37) event.preventDefault();} //-- backspace, left cursor
}
halfEditable_INPUT.prototype.PRIVATE_setValue=function (value) {this.element.value=value;}
halfEditable_INPUT.prototype.PRIVATE_getValue=function () {return this.element.value;}
//-----------------------------------------------------
//-------- prototype -- END
//-----------------------------------------------------
//***************************************************************
//-------------------------------------- Class halfEditable_INPUT -- END
//***************************************************************
var inputA=new halfEditable_INPUT(document.getElementById ("inputA"));
if you have further questions let me know.