Card Elevation on Click

Hi how can I convert this interaction from being on hover animation to ‘on click’ instead?

Without JavaScript this will be pretty challenging, but not impossible. One place to start is to switch out the line that says .block:hover to .block:active, but you have to hold the click down.

Another way to do it would be to make those elements empty anchors, and then use .block:focus instead - then you only have to click it once without holding.

If the above ways don’t work then I can try and show you a way with JavaScript

hmm focus is not working on me. curious to know if it works for you?

Yes, It’s always best to use JS for the behavior layers of a webpage.

It could probably be done with the checkbox hack, but it would end up as a hack like the name suggest.

Just take the :hover rules and give it a classname. Then toggle that new class on click.

2 Likes

Totally! This was posted in HTML & CSS and for whatever reason at the time I thought they specifically wanted a CSS solution. In fact, I think I’ve linked to that exact article myself :joy:

2 Likes

Sometimes we have to nudge people in the right direction. :grinning:
Your right, it’s a job for JS

1 Like

AFAIK, the :focus (and :focus-within) pseudoclass will work only with elements that can get focus such as form inputs, links. i.e. the ones you can navigate to by tabbing. A <div> is not such an element.

It might be made to work by giving it a tab index, or maybe using something other than a <div> or using :focus-within but I agree that if a click event is wanted then JavaScript would most likely be the easiest and cleanest even if not the most “wow, I didn’t know you could do that” approach.

1 Like

You can use target for a more persistent effect (within limitations) but as others have suggested JS is probably a better approach if you want to reverse the animation on second click.

I just forked your pen to show target in action.

Not sure why you were using keyframes for a simple scale when transitions would do but I guess its part of a bigger concept.

1 Like

not really familiar with css3 thats y.

<off-topic>
That’s a new one for me.
And exactly what I need right now.
Useful for keyboard tabbable menus that use hover to show/hide, but where focus in the child menu item does not reveal the parent menu.
I recall puzzling this problem previously, as there was no selector where a child could influence the styling of the parent.
</off-topic>

3 Likes

Yes its a very useful addition and the rare case where a child can influence the parent. :slight_smile:

3 Likes

To avoid the page jump when using target you can use position:fixed for the target which stops the page scrolling to the destination but it means you have to use an adjacent selector to then get to the element in question.

Also if you want to close the element with another click you can add another anchor inside which will lose the target on the parent and reverse the effect.

Here is a revised codepen showing both in action although it does add to the html a little.

Now you can click to close the element if required.

Of course as I mentioned JS is probably better served to do this by simply swapping a class on the parent and you can leave the html unchanged. However if no JS is a requirement then the above will work quite well.

1 Like

New to me too :slight_smile:

Yes, you can put any element in focus with tabindex.
However I do see that it is discouraged in the Accessibility concerns for divs.

Avoid using the tabindex attribute in conjunction with non-interactive content to make something intended to be interactive focusable by keyboard input. An example of this would be using an <div> element to describe a button, instead of the <button> element.

If indeed it is interactive content it sounds like the button would be the better choice. Even if it is just for visual changes when using :focus

In the OP’s case I would assume this is interactive content since it requires the user to interact with it. Of course my assumption seems to apply to the use of tabindex and focus.

It’s still fun playing with the :focus-within pseudo selector though :slight_smile:

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>:focus-within</title>
<style>
h1 {text-align:center}

.wrap {
  display:flex;
  flex-flow: row wrap;
  justify-content: space-evenly;
  width:70%;
  margin:auto;
  padding:20px;
  border:1px solid;
  background:silver;
}
.wrap div,
.wrap button {
  min-width:140px;
  margin:10px;
  padding:20px 0;
  background:lime;
  border:0;
  font-size:1em;
  text-align:center;
  transition:transform 0.5s;
  cursor:pointer;
}
.wrap:focus-within {
  background: gray;
}
.wrap div:focus,
.wrap button:focus {
  transform:scale(1.4);
  background:yellow;
  outline:none;/* we have other styles indicating it is in focus*/
}
.wrap button::-moz-focus-inner {border:0;}
</style>

</head>
<body>

<h1>Using Divs and tabindex</h1>
<div class="wrap">
   <div tabindex="0">div 1</div>
   <div tabindex="0">div 2</div>
   <div tabindex="0">div 3</div>
   <div tabindex="0">div 4</div>
</div>

<h1>Using Buttons</h1>
<div class="wrap">
   <button>button 1</button>
   <button>button 2</button>
   <button>button 3</button>
   <button>button 4</button>
</div>

</body>
</html>
2 Likes

Here is the OP’s example using buttons and :focus

I wonder if it’s possible to close the button that is in focus with a second click using CSS.

As it is now I have to click outside of the parent to remove focus

I know I have already made my arguments against :target in other threads. But this does dramatically reduce the HTML/CSS while preserving the browser history. It’s tab able with the keyboard too.

<!DOCTYPE HTML>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Cards Scale UI - :focus</title>
<style>
body {
  font-family: "Roboto Condensed", sans-serif;
}
.content {
  height: 400px;
  width: 700px;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  box-shadow: 10px 10px 60px 10px rgba(0, 0, 0, 0.1);
}
button {
  position: absolute;
  border: 0;
  font-size: 1em;
  text-align: center;
  transform: scale(1);
  transition: all 1s ease;
  box-shadow: 10px 10px 60px 10px rgba(0, 0, 0, 0);
  cursor: pointer;
}
.x1 {
  width: 200px;
  height: 150px;
  left: 0;
  top: 0;
  background: #9cb1ff;
}
.x2 {
  height: 250px;
  width: 300px;
  left: 400px;
  top: 0;
  background: #ffffff;
  color: black;
}
.x3 {
  height: 250px;
  width: 200px;
  left: 0;
  top: 150px;
  background: #6694fc;
}
.x4 {
  height: 150px;
  width: 500px;
  left: 200px;
  top: 250px;
  background: #706af3;
}
.x5 {
  height: 250px;
  width: 200px;
  left: 200px;
  background: #8593e6;
}
button:focus {
  z-index: 1;
  transform: scale(1.2);
  box-shadow: 10px 10px 60px 10px rgba(0, 0, 0, 0.8);
  pointer-events: none;
}
button::-moz-focus-inner {border:0;}
button:hover{z-index:2;}

</style>

</head>
<body>
  <div class="content">
    <button class="x1">Click Me!</button>
    <button class="x2">Or Click Me!</button>
    <button class="x3">Try Clicking Here</button>
    <button class="x4">Last But Not Least</button>
    <button class="x5">Now Here!</button>
  </div>
</body>
</html>

Ahh! Just found the answer…
pointer-events: none;

Code above updated with that change. Now it’s click to open/close.

3 Likes

Good demos Ray :slight_smile:

However realistically I think there are also too many problems with using :focus for this type of thing unless its a simple demo (an image enlarging perhaps) but for real content it’s a bit problematic as focus is lost as soon as some other part of the page is clicked with the mouse (which would be fine for an effect such as an image enlargement but not for viewing extra content).

Also :focus doesn’t really work on touch devices and you would need to use :hover as well to get a first-touch effect working but then of course you can’t dismiss the effect by clicking again. It also spoils the desktop version as hover takes effect straight away. I know you could use the :hover or :pointer media queries to counter the effects but then once again things start to get more complex than a simple js version with a class.

To get your demo to work on ios you could add ontouchstart to the body (<body ontouchstart="">) tag but once again you are adding js in an attempt to help css so why not use JS as you already mentioned.

The main problem with using :target is the extra html and the history (back button) problem. The page jump can be nullified as in my demo but does need the extra html.

The history (back-button) problem in itself is simply a by-product of the in-page fragment identifier and in the case of tabbable content I think it does the job intended in that it goes back to the last link clicked. Of course if you have clicked the tabs many times then the back button cycles through all those choices in order which can be a bit disconcerting and probably best avoided.

In a normal page (forget tabs for now) with ‘in-page’ fragment identifiers the back button also goes back to the last fragment identifier clicked and the same problem as with tabs can appear in that the back-button will cycle through all the same page links in order until it reaches the end and then goes back to a previous site. That’s why some people say avoid using in-page fragment identifiers where possible.

Bearing in mind the shortcomings of most of the methods above then a simple js class switch is usually the best option. You can of course enhance the design to fallback to a css solution if js is not available and have the best of both worlds.

One point we haven’t established though is whether the OPs demo is a simple effect with a link or whether there is some actual content to be revealed in the enlarged sections. If this is just a pretty effect then I think any of the methods above could be suitable :slight_smile:

3 Likes

I agree completely! It was just a simple demo for enlarging an image on desktops.

The first thing I said in post #4 was that it would best to use JS to toggle a class. From that point onward it was just playing with CSS for the sake of fun :slightly_smiling_face:

Yes it has the same function of a fragment identifier, hence the need for ID’s to make it work. If it’s a section of a page you wish to jump too, then I agree you would expect to return to the last link you clicked.

I’m not saying :target has no usefulness to it. I find the browser history problem a nuisance when clicking through tabbed content or in this case an image gallery type setup. I’m the type of person that uses my back button constantly when browsing.

So if I’m looking through 20 images on a gallery page and I want to jump back to the previous page I was on. I will reach for my back button before I look for a link in the gallery page to get me back to where I was. I think we both agree that is where it’s a problem. The average person that doesn’t know anything about fragment identifiers. They get confused as to why their back button is cycling back through all the images they just viewed.

I was looking at the HTML of the OP’s first post. There were no anchors for links so it lead me to think that it was just to elevate the cards on click (thread title).

Would I use :focus for this? Absolutely not :slight_smile:

2 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.