4

Got very vague and unwanted answers from this question so I have decided to post a clear question briefing the problem I am facing.

The code I'm using looks like this:

.flipClass {  
            font-size: Large;
            background-color: #4399CD; 
            color:#fff;
            text-align: left;
}

.flipClass:active{
                  background:#fff; 
                  color:#4399CD;
                  cursor:pointer;
                  transition:all .1s ease-out;
}
.flipClass:active:before {
                          content:'\f102';
                          font-family:FontAwesome;
                          font-style:normal;
                          font-weight:normal;
                          text-decoration:inherit;
                          padding-left:6px; 
                          padding-right:8px;
                          transition:all .3s;
}

How would I go about getting the CSS style defined by .flipClass:active after I have clicked the element? Currently, It is becoming active for a brief period of time only.

Please look at the snippet given below:

 $("div[id^=flip]").click(function() {
   $(this).next("div[id^=panel]").stop().slideToggle("slow");
 });
.panelClass,
.flipClass {
  padding: 5px;
  padding-left: 15px;
  border: solid 1px #c3c3c3;
}
.flipClass {
  font-size: Large;
  background-color: #4399CD;
  color: #fff;
  text-align: left;
}
.flipClass:active {
  background: #fff;
  color: #4399CD;
  cursor: pointer;
  transition: all .1s ease-out;
}
.flipClass:active:before {
  content: '\f102';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}
.panelClass {
  padding: 30px;
  padding-top: 10px;
  display: none;
  background-color: #F3F5F6;
  color: #000;
}
.flipClass:before {
  content: '\f107';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />Currently, the .flipClass:active CSS style sheet is working only for a brief moment (precisely until the duration of the mouseclick and maybe some small offset). Click and HOLD mouseclick when clicking on .flipClass to see the effect. I want it to stay!
<div class="flipClass" id="flip1">FIRST HEADING</div>
<div class="panelClass" id="panel1">How to keep the first heading 'active' when this panel is showing? If I could figure that out, I could change the arrow to a pullup arrow too :3</div>
<div class="flipClass" id="flip2">SECOND HEADING</div>
<div class="panelClass" id="panel2">If both Headings have been clicked, this Heading and any other heading that were clicked should also be active (or atleast remain in the CSS state defined by .flipClass:active here)</div>

Currently, the .flipClass:active CSS style sheet is working only for a brief moment (precisely until the duration of the mouseclick and maybe some small offset). I require a method to keep it active all the time after flipClass is clicked. Am I using an inappropriate pseudo selector for this?

Is there some workaround? or is there some another pseudo selector specific for this purpose? may I get an example?

Community
  • 1
  • 1
Siddhant Rimal
  • 975
  • 2
  • 11
  • 32
  • Use `:focus` instead – Aziz Apr 11 '16 at 17:35
  • One way would be to use hidden `checkbox`en and `label`s for them; Make your headings the `label`s, tie the `:active` style to `:checked + .flipClass`. Bonus, you can move your accordion into css as well, via `:checked + .flipClass + .panelClass`. Side note, postfixing your class names with "Class" is a tad extremely redundant. – abluejelly Apr 11 '16 at 17:39
  • @Aziz `:focus` will only work until they click on something else, which is not quite the behavior he wants.He wants the style to stick based on whether or not its panel is displayed, or at least that the most recent one opened is kept `:active` – abluejelly Apr 11 '16 at 17:41
  • Could also implement it via `:target` if you only want the most recent one to have the style stick; only addition then is needing a self-pointing `a`nchor – abluejelly Apr 11 '16 at 17:44

3 Answers3

2

For elements that accept user input focus, such as button elements, the :focus pseudo-class comes close to what you want. But in this case it looks like you can expand multiple sections, so :focus won't cut it here.

Instead, you can just use JS to apply an extra class, like so:

$("div[id^=flip]").click(function() {
   $(this).toggleClass("flipClass-active").next("div[id^=panel]").stop().slideToggle("slow");
 });
.panelClass,
.flipClass {
  padding: 5px;
  padding-left: 15px;
  border: solid 1px #c3c3c3;
}
.flipClass {
  font-size: Large;
  background-color: #4399CD;
  color: #fff;
  text-align: left;
  cursor: pointer;
  transition: all .1s ease-out;
}
.flipClass-active,
.flipClass:active {
  background: #fff;
  color: #4399CD;
}
.flipClass::before {
  content: '\f107';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}
.flipClass-active::before,
.flipClass:active::before {
  content: '\f102';
}
.panelClass {
  padding: 30px;
  padding-top: 10px;
  display: none;
  background-color: #F3F5F6;
  color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />Currently, the .flipClass:active CSS style sheet is working only for a brief moment (precisely until the duration of the mouseclick and maybe some small offset). Click and HOLD mouseclick when clicking on .flipClass to see the effect. I want it to stay!
<div class="flipClass" id="flip1">FIRST HEADING</div>
<div class="panelClass" id="panel1">How to keep the first heading 'active' when this panel is showing? If I could figure that out, I could change the arrow to a pullup arrow too :3</div>
<div class="flipClass" id="flip2">SECOND HEADING</div>
<div class="panelClass" id="panel2">If both Headings have been clicked, this Heading and any other heading that were clicked should also be active (or atleast remain in the CSS state defined by .flipClass:active here)</div>
emackey
  • 11,818
  • 2
  • 38
  • 58
  • Perfectly fits the question. +1. But may I get your opinion on @abluejelly's answer. He/She has used a completely CSS based answer. Its creative to say the least but I want to know if it makes the performance better in any way. And if that approach has limited support somewhere? – Siddhant Rimal Apr 12 '16 at 02:54
  • hmm now that I notice, I wonder why the dropdown arrow remains unchanging..hmm... the code seems to be in place. I wonder what the problem is – Siddhant Rimal Apr 12 '16 at 09:10
  • 1
    You had some rules out-of-order, the non-active rules were able to override the active rules. I edited my answer to fix the problem. @abluejay's answer should also work, I don't expect any performance difference, but it might be trickier to maintain. 8 months from now when someone finds or introduces a bug, will you remember why there are hidden checkboxes and checked states? It's clever but seems like it would take some re-figuring out in the future. – emackey Apr 12 '16 at 13:33
  • @emackey Which is why you can just slap a `` that explains a "static accordion" and links back to where you got the idea from. You know, like you should do with all StackOverflow code so it's more maintainable. Related, the core design of my no-js solution should become more common with time as people realize they *can* do that, as the rareness of it is a mix of the web's abhorrence of change and desire for backwards compatibility (IE 8 only went EoL *this* year). Sorry for the late response, it's `jelly` not `jay`, I'm named for a creature from NetHack, not a bird haha – abluejelly May 05 '16 at 18:15
1

Ditching jQuery, exploiting the :checked pseudoclass, labels, and the + selector, we can actually go native and static!

This means we have to animate the max-height of a revealing panel ourselves. Because we have to animate the entire max-height rather than just the content height, we have to trick the eye into making the animation less extreme than it is. To do that, animate the top/bottom padding as well- and let the viewer's eye do the rest.

Drawback of this solution, you have to be able to reliably place an upper bound on the height of your panel. This can be alleviated somewhat by adding overflow:auto; after the animation finishes, but I'll leave how to do that as an exercise to the reader.

.panelClass,
.flipClass {
  display:block;
  padding: 5px;
  padding-left: 15px;
  border: solid 1px #c3c3c3;
}

.flipClass {
  font-size: Large;
  background-color: #4399CD;
  color: #fff;
  text-align: left;
  cursor:pointer;
}
.flipClass:before {
  content: '\f107';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}
:checked + .flipClass {
  background: #fff;
  color: #4399CD;
  transition: all .1s ease-out;
}
:checked + .flipClass:before {
  content: '\f102';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}

.panelClass {
  /*display: none;/*We have to animate this ourselves now*/
  padding:0 30px;
  max-height:0;
  background-color: #F3F5F6;
  color: #000;
  transition:all 450ms ease-in-out;
  overflow:hidden;
}
:checked + .flipClass + .panelClass{
  max-height:900px;
  padding-top: 10px;
  padding-bottom: 30px;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />Currently, the .flipClass:active CSS style sheet is working only for a brief moment (precisely until the duration of the mouseclick and maybe some small offset). Click and HOLD mouseclick when clicking on .flipClass to see the effect. I want it to stay!
<input type="checkbox" id="flip1" hidden />
<label class="flipClass" for="flip1">FIRST HEADING</label>
<div class="panelClass" id="panel1">How to keep the first heading 'active' when this panel is showing? If I could figure that out, I could change the arrow to a pullup arrow too :3</div>
<input type="checkbox" id="flip2" hidden />
<label class="flipClass" for="flip2">SECOND HEADING</label>
<div class="panelClass" id="panel2">If both Headings have been clicked, this Heading and any other heading that were clicked should also be active (or atleast remain in the CSS state defined by .flipClass:active here)</div>

Another option would be to use :target (MDN) to "store" the most-recently-selected option... however that would cause weird behavior should a user bookmark the page after opening one, some additional logic to handle clicking it to close it, and would only be able to tag one item. If you want a reveal-only-one accordion, this is definitely a good choice for how to do it. Alternatively, you could swap the checkboxen in the above code for radio buttons.

abluejelly
  • 1,266
  • 9
  • 17
  • I like @emackey's answer as it fits my purposes with little change. However in your brilliant implementation, it seems no javascript, and extension jQuery, is used. Does that mean that this loads my page faster? I am willing to use this implementation if you can tell me whether or not it will affect my site negatively in any way. I prefer non-native because it is reliable. I want to know the reliability of this approach. Will it work. Always? Any exceptions? – Siddhant Rimal Apr 12 '16 at 02:51
  • I implemented it on a blog of mine. Would work wonders on a website but it seems this produces errors on blogger because certain attributes of are not properly supported and blogger tries to format the code automatically.. which messes up a lot of things. Nevertheless, it is an excellent solution!! – Siddhant Rimal Apr 12 '16 at 09:12
  • @lancel0t Native implies a lack of jQuery (or any other external library), which is all but always going to be more performant (jQ is especially famous for being sluggish and bloated). Removing Javascript means the page will be _generally_ quicker (it's defined statically), and people running NoScript or similar will not suffer accessibility problems. Disadvantages, [IE 8 and earlier](http://caniuse.com/#feat=css-sel3) will suffer accessibility problems (unable to unhide text), and IE 9 will lack the sliding animation. Note that IE 8 has been EoL since mid-January 2016 – abluejelly Apr 13 '16 at 20:00
0

You can't do this with :active in CSS. One way to keep the link active is to add a class with your script, like this

$("div[id^=flip]").click(function() {
   $(this).toggleClass('active').next("div[id^=panel]").stop().slideToggle("slow");
 });

.flipClass.active {
  background: #fff;
  color: #4399CD;
  cursor: pointer;
  transition: all .1s ease-out;
}
.flipClass.active:before {
  content: '\f102';
  font-family: FontAwesome;
  font-style: normal;
  font-weight: normal;
  text-decoration: inherit;
  padding-left: 6px;
  padding-right: 8px;
  transition: all .3s;
}

:active will only apply the style when the mouse button is held down. The only way to apply a style and keep it applied onclick is to use a bit of JavaScript.

(source of this quote : Can I have an onclick effect in CSS?)

Community
  • 1
  • 1
Vincent G
  • 8,547
  • 1
  • 18
  • 36