I am trying to make a button, such that when the user clicks on it, it changes its style while the mouse button is being held down. I also want it to change its style in a similar way if it is touched in a mobile browser. The seemingly-obvious thing to me was to use the CSS :active pseudo-class, but that didn't work. I tried :focus, and it didn't work too. I tried :hover, and it seemed to work, but it kept the style after I took my finger off the button. All of these observations were on an iPhone 4 and a Droid 2.
Is there any way to replicate the effect on mobile browsers (iPhone, iPad, Android, and hopefully others)? For now, I am doing something like this:
<style type="text/css">
#testButton {
background: #dddddd;
}
#testButton:active, #testButton.active {
background: #aaaaaa;
}
</style>
...
<button type="button" id="testButton">test</button>
...
<script type='text/javascript' src='http://code.jquery.com/jquery-1.6.1.min.js'></script>
<script type='text/javascript'>
$("*").live("touchstart", function() {
$(this).addClass("active");
}).live("touchend", function() {
$(this).removeClass("active");
});
</script>
The :active pseudo-class is for desktop browsers, and the active class is for touch browsers.
I am wondering if there is a simpler way to do it, without involving Javascript.
There is no such thing as :touch in the W3C specifications, http://www.w3.org/TR/CSS2/selector.html#pseudo-class-selectors
:active should work, I would think.
Order on the :active/:hover pseudo class is important for it to function correctly.
Here is a quote from that above link
Interactive user agents sometimes change the rendering in response to user actions. CSS provides three pseudo-classes for common cases:
The :hover pseudo-class applies while the user designates an element
(with some pointing device), but does
not activate it. For example, a visual
user agent could apply this
pseudo-class when the cursor (mouse
pointer) hovers over a box generated
by the element. User agents not
supporting interactive media do not
have to support this pseudo-class.
Some conforming user agents supporting
interactive media may not be able to
support this pseudo-class (e.g., a pen
device).
The :active pseudo-class applies while an element is being activated by
the user. For example, between the
times the user presses the mouse
button and releases it.
The :focus pseudo-class applies while an element has the focus
(accepts keyboard events or other
forms of text input).
Since mobile doesn't give hover feedback, I want, as a user, to see instant feedback when a link is tapped. I noticed that -webkit-tap-highlight-color is the fastest to respond (subjective).
Add the following to your body and your links will have a tap effect.
body {
-webkit-tap-highlight-color: #ccc;
}
I was having trouble with mobile touchscreen button styling. This will fix your hover-stick / active button problems.
body, html {
width: 600px;
}
p {
font-size: 20px;
}
button {
border: none;
width: 200px;
height: 60px;
border-radius: 30px;
background: #00aeff;
font-size: 20px;
}
button:active {
background: black;
color: white;
}
.delayed {
transition: all 0.2s;
transition-delay: 300ms;
}
.delayed:active {
transition: none;
}
<h1>Sticky styles for better touch screen buttons!</h1>
<button>Normal button</button>
<button class="delayed"><a href="https://www.google.com"/>Delayed style</a></button>
<p>The CSS :active psuedo style is displayed between the time when a user touches down (when finger contacts screen) on a element to the time when the touch up (when finger leaves the screen) occures. With a typical touch-screen tap interaction, the time of which the :active psuedo style is displayed can be very small resulting in the :active state not showing or being missed by the user entirely. This can cause issues with users not undertanding if their button presses have actually reigstered or not.</p>
<p>Having the the :active styling stick around for a few hundred more milliseconds after touch up would would improve user understanding when they have interacted with a button.</p>
The much upvoted comment by #gion_13 solved the issue for me:
Add ontouchstart="" to your page's body element and the :active selector will work more as expected on touch screens. Still not perfect in Chrome.
Related
Is there any CSS prefix for night mode or javascript event that trigger when user change the mode? I want custom colors for the element if the user enables night mode from the browser setting.
Thanks
It’s almost 2020 and we have now css media query to detect night mode.
#media (prefers-color-scheme: dark){
body {
background-color: black;
color: #ccc;
}
}
There is a CSS filter, I'm not sure that Twitter used something like this (no images were inverted only text and background.
note1: you can lower index of invert filter, for ex: .8
note2: no IE support :( but Edge support it
$('button').on('click', function(){
$('.wrap').toggleClass('day night') ;
});
.wrap{
background: white;
}
.day{
filter: invert(0);
}
.night{
filter: invert(1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap day">
<img src="https://placeimg.com/200/150/any" />
<p>Lorem ipsus </p>
<button>Day / night</button>
</div>
Actually, today we can not only use #media (prefers-color-scheme: dark) in CSS like you've mentioned, but also check with js
const isDarkMode = window.matchMedia &&
window.matchMedia('(prefers-color-scheme: dark)').matches
and listen to changes in it:
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', event => {
if (event.matches) {
//dark mode
} else {
//light mode
}
})
(gratefully copy-pasted from this article, which may be not the original as the code is repeated in several others)
I'm not sure how to determine whether current browser will detect anything with these. I presume one should check if window.matchMedia('(prefers-color-scheme: dark)') is an object, but this is only my hypothesis, I haven't found any definitive info about this.
Because "night mode" will involve not only changing the background color, but also font colors (plus potentially a lot of other things) I would recommended a solution such as this:
Example HTML:
<body class="night">
Now, in standard mode the body tag wouldn't have the night class by default, but you would add this via a toggle class function such as jQuery's toggleClass.
Then in the CSS do something like...
CSS:
body {
color: #000;
background-color: #fff;
}
body.night {
color: #fff;
background-color: #000;
}
NB: Example only, please don't use white text on a black background :)
Now when the class is toggled and the night class is added, all the colors will change and the page will be in "night" mode.
Unsure if you also want instructions on making this mode "stick" during page refresh/navigation; if so, that is probably best handled with a session or a cookie that expires on browser close.
I have a DIV with the following CSS code attached:
.active,#foo:active {background-color: rgba(0,0,0,0.75)}
In addition, I have set up keydown and keyup javascript routines to convert a selected keypress to add and remove the 'active' class, darkening it accordingly. My problem is when the user clicks on the DIV (darkening it as expected)...but in a setInterval I have running, polling the DIV and several more like it periodically to get state information, I run into the problem of not being able to tell the current DIV state.
Getting the state via the active class is easy enough. I simply have to do this...
document.getElementById("foo").classList.contains("active")
That gives me a boolean on/off I can use, but the following does not work to read a mouse long click.
document.getElementById("foo").classList.contains(":active")
This is because activated pseudoes do not show up in classList. I tried rewriting the mouse-examining check to look like this:
document.getElementById("foo") === document.activeElement
But as the element is a DIV, this never resolves to a true as document.activeElement stays stuck on the BODY element of the page. I also tried looking at the current background-color, but the following doesn't update when :active is in use.
document.getElementById("foo").style.backgroundColor === "rgba(0,0,0,0.75)"
Is there another way to proceed without needing to resort to removing :active from the CSS and installing onclick() and onmouseout() to my code? Using that particular workaround does not scale well depending on how many DIVs I set up in this fashion. I would much rather detect when the DIV is currently using the CSS rule described above.
Please, no jQuery solutions or external libraries. I want to use vanilla JavaScript.
Pseudo elements are not part of the DOM so you cannot trigger events on them.
https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
In addition .style prototype function does not work as intended, to look for computed style use
var ele = document.querySelector('.example-value')
window.getComputedStyle(ele, null).backgroundColor === "rgba(0,0,0,0.75)"
https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
Polling to get the current state of an element is a bad idea, instead use events.
When polling, you are making CPUs always process for nothing, it can make your page irresponsible, cause useless bottlenecks, but most of all, it consumes a lot of electricity for nothing. Always think about the trees when coding.
But one has to admit that for the :active status, it may be a bit cumbersome to listen to all the events that can trigger it.
So we've got to be a bit smarter, and create our own event from there.
We can create an empty animation triggered only in the :active state.
Then we just have to listen for the animationstart event to act as an replacement for our pseudo-class activation event.
/* older browsers might need vendor prefixes... */
foo.addEventListener('animationstart', function(evt){
// to be sure it's our correct event, we check for the animationName
console.log('active', evt.animationName === 'active');
});
#foo:active{
background-color: #FAFFAA;
-webkit-animation: active 0s linear;
-o-animation: active 0s linear;
-ms-animation: active 0s linear;
animation: active 0s linear;
}
#keyframes active{}
#-webkit-keyframes active{}
#-o-keyframes active{}
#-ms-keyframes active{}
<div id="foo">
click me to activate me
</div>
And if ever you need to know at any time if an element has an pseudo-class, you can use Element.matches(cssRule).
The word "active" has different meanings:
An element with the :active pseudo-class. This means the element is in the process of being clicked, usually. This is most commonly used for creating some visual effect when the user mouse-downs on a button, and remove it when he mouse-ups, for example. This is probably not relevant to your use case.
The element given by document.activeElement. This does not mean the element with the :active pseudo-class; it means the element with focus. It will be the body if there is no specific focus, or it could be some input element, or it could be any other element with a tabindex attribute. This is also the element with the :focus pseudo-class. An element can be focused by clicking on it, or tabbing to it, or calling HTMLElement#focus on it.
Some application-defined concept of "active", such as the currently active tab in a tabbed interface, often represented by the presence of a user-defined class on the element, such as your .active.
In general, people write far too much JavaScript to check things, or intercept events, or set magic variables, or add and remove classes or even local styles, or in the worst jQuery style add and remove elements from the DOM, or God forbid do polling, when in many cases CSS could handle what needs to be done if used properly. A trivial example is writing mouseover handlers when :hover could do the job.
I don't fully understand what you are trying to accomplish, or what the desired behavior is. However, the following code might give you some clues:
const activeElement = document.getElementById("activeElement");
const divElement = document.getElementById("div");
function showActiveElement() {
activeElement.textContent = document.activeElement.tagName;
}
function updateActiveElement() { setInterval(showActiveElement, 500); }
function setFocus() { divElement.focus(); }
updateActiveElement();
/* Show a message if the div is active (being clicked on). */
#activeMessage { display: none; }
#div:active ~ #activeMessage { display: block; }
/* Show a message if the div is focused. */
#focusMessage { display: none; }
#div:focus ~ #focusMessage { display: block; }
/* Style the div when it is focused. */
#div:focus { background-color: rgba(0, 0, 0, 0.75); color: white; }
#div { border: 1px solid gray; }
<p>
Here is the div we are working with.
Click on it, or tab to it, to give it the focus.
</p>
<!-- The div in question. Give it a tabindex to allow focus. -->
<div id="div" tabindex="1">
Hello Bob
</div>
<p id="activeMessage">
The div is active, in the sense that the mouse is being clicked on it, and
therefore its <tt>:active</tt> pseudo-class is set.
</p>
<p id="focusMessage">
The div is active, in the sense that it has the focus,
therefore its <tt>:focus</tt> pseudo-class is set.
<p>
The element with focus at the moment (<tt>document.activeElement<//tt>) is
<span id="activeElement"></span>
</p>
<button onclick="setFocus()">Make the div focused ("active")</button>
Can anyone tell me why button focus borders are rendered with a black dashed border by default in IE11 and with a blue solid border in Chrome? You can see this if you go to http://angular-ui.github.io/ and tab over the Site/Code buttons with IE11 and Chrome.
I've tried various overrides like -webkit-appearance:none etc to no avail. Is this an AngularUI bug, or a browser quirk everybody knows about and have been working around that I'll need to special-case if I want the look to be uniform?
When you tab over the button, you are applying the element's :focus styling. Looking at the stylesheet which is being used, I cannot see any custom styling for this, so the browser is providing it's default focus styling.
If you want to override this, then you can write your own focus style. So for this particular button, you can use:
a.btn.btn-primary.btn-large:focus{
outline: 0;
/* add other styling to it */
}
Or if you want to just target all anchors on the page, then use
a:focus{
outline: 0;
}
Angular is adding the dotted lines on this occasion - to remove, do this in your CSS;
.btn-group > .btn:hover, .btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active {
outline: 0;
}
I have written piece of javascript for close button, but when i hover my mouse to close button mouse icon is not changing to hand, so i am not able to close it, however hand appears at some points of the close button
I am facing this issue on firefox and chrome
IE is working fine
Below is some part of it
href="javascript:closeWin()"
keephref="javascript:closeWin()"
style="cursor: default;
Below is its css
element.style {
cursor: default;
}
The default is the normal arrow. Pointer is the hand.
style="cursor: pointer;
element.style {
cursor: pointer;
}
Add CSS cursor:pointer; which shows a pointing hand cursor.
If you are using <a> tag then dont add cursor:default; to it because an <a> tag already displays pointing cursor.
If you want to show hand cursor use this CSS for your close anchor
a.close {
cursor: default; /* modern browsers */
cursor: hand; /* old IE - property is ignored by others */
}
If the tag is a link, remove the style since the href will give the hand
Close
I do not know what you need the keephref for, but it is not recommended to use javascript: protocol for a link
As AlienArrays and Zword said, the default cursor means normal arrow cursor.
If you want the default browser behaviour over an element, use:
style="cursor: auto;"
You can also use the pointer value if you want to force "hand" style cursor, ie. to indicate that something that normally is not clickable will perform an action when clicked.
You can check :hover attribute in css
#element :hover
{
cursor:pointer;
}
Is there a way to do this? It differs from browser to browser what outline is displayed and such (Safari and its blue glow, Firefox and its dotted outline when clicking a submit button...)
CSS is preferable, but JS is fine too.
The outline can be removed by resetting the outline property:
input:focus, button:focus, textarea:focus, select:focus {
outline: 0;
background-color: #efefef;
}
However, you should include another visual indicator, as I have done here, to indicate that the element is focused, for accessibility reasons.
I believe you're talking about the outline property. To remove outlines you can do this;
element { outline:none; }
Although I don't recommend it for usability reasons.
If you change the default properties of the items in CSS, such as border, background and the like, the default appearance of those elements will no longer prevail.
You can set borders of widths, colors and styles as you like for buttons, inputs and fieldsets, for example. Also, the background (colors and/or images) will alter those default appearances.
selector{
outline:none;
}
Si Yi Jiang's answer for a code-level solution. There's also a good article on Sitepoint.
The blue glow (focus ring) in Safari is a Mac OS X user preference. The user can adjust how/when that appears.
in System Preferences > Keyboard > Keyboard Shortcuts > Full Keyboard Access, check "Text boxes and lists only"
in Safari > Preferences > Advanced > Universal Access, uncheck "Press Tab to highlight each item on a web page"