0

I am working on a proof of concept - a module written in javascript which extends the capabilities of conventional CSS.

I'm happy with what I have put together so far (although there is a lot more to do), and I have reached a suitable stage where I need to look back and double-check that haven't missed something mind-numbingly obvious.

Please look at the styled markup below. The two examples on the left are styled with conventional CSS. The two examples on the right are styled with the module I have written - which I have called ACSSSS (Augmented CSS Selector Syntax) or axe for short.

Question: Is it possible to achieve the presentation of the two examples on the right with conventional CSS alone? (And if so, how?)


Update (April 2017)

Two and a bit months after I first posted this question, @Ferrybig has pointed out in the comments below that in any StackSnippet I need to link to the external axe script via an https:// connection. All fixed! You can now open up the code snippet below and see all the axe selectors in action.

/******************
GENERAL STYLE RULES
******************/

body, div, h2, ul {
transition: all .75s ease-out;
}

div {
display: inline-block;
width: 190px;
margin: 6px;
padding: 12px;
border: 1px dashed rgb(127,127,127);
text-align: center;
vertical-align: top;
}

h2 {
line-height: 36px;
margin: 0;
font-size: 18px;
font-family: arial, helvetica, sans-serif;
}

ul {
padding-left: 12px;
color: rgb(255,255,255);
text-align: left;
background-color: rgb(0,0,127);
border: 6px solid rgb(0,0,0);
border-radius: 15px;
box-shadow: 4px 4px 4px rgba(127,127,127, 0.5);
list-style: none;
}

li {
height: 48px;
max-height: 48px;
font-size: 24px;
line-height: 48px;
margin-left: -12px;
padding-left: 12px;
transition: all 0.5s ease-out;
}

li:first-of-type {
border-radius: 9px 9px 0 0;
}

li:last-of-type {
border-radius: 0 0 9px 9px;
}

li:hover {
margin-left: -12px;
padding-left: 12px;
cursor: pointer;
}

.axe-info {
position: absolute;
top: 0;
left: 0;
height: 24px;
line-height: 24px;
font-size: 18px;
color: rgb(255,255,255);
text-align: center;
padding: 12px 24px;
border-radius: 24px;
opacity: 0;
transform: translateX(-600px);
transition: all 0.75s linear;
}

.axe-info strong {
font-size: 26px;
}

.rainbow-list li:hover ~ li,
.priority-list li:hover ~ li {
color: rgba(255,255,255,0.5);
}

div + hr {
margin-top: 120px;
}

hr ~ ol li {
height: auto;
max-height: none;
}

code {
display: inline-block;
padding: 0 12px;
}

/***********
RAINBOW LIST
************/

.rainbow-list li:hover {
background-color: red;
}

.rainbow-list li:hover + li {
background-color: orange;
}

.rainbow-list li:hover + li + li {
background-color: yellow;
}

.rainbow-list li:hover + li + li + li {
background-color: green;
}

.rainbow-list li:hover + li + li + li + li {
background-color: blue;
}

.rainbow-list li:hover + li + li + li + li + li {
background-color: indigo;
}

/************
PRIORITY LIST
*************/

.priority-list li:hover {
font-size: 36px;
background-color: rgba(255,255,255,0.6);
}

.priority-list li:hover + li {
background-color: rgba(255,255,255,0.3);
font-size: 30px;
}

.priority-list li:hover + li + li {
font-size: 24px;
}

.priority-list li:hover + li + li + li {
background-color: rgba(0,0,0,0.3);
font-size: 18px;
}

.priority-list li:hover + li + li + li + li {
background-color: rgba(0,0,0,0.6);
font-size: 12px; 
}

.priority-list li:hover + li + li + li + li + li {
background-color: rgba(0,0,0,0.9);
font-size: 6px; 
}

/*********************
RAINBOW LIST WITH AXE
*********************/

.rainbow-list-with-axe li:hover ? li ? li ? li ? li ? li ? li,
.rainbow-list-with-axe li:hover {
background-color: red;
}

.rainbow-list-with-axe li:hover ? li ? li ? li ? li ? li,
.rainbow-list-with-axe li:hover + li {
background-color: orange;
}

.rainbow-list-with-axe li:hover ? li ? li ? li ? li,
.rainbow-list-with-axe li:hover + li + li {
background-color: yellow;
}

.rainbow-list-with-axe li:hover ? li ? li ? li,
.rainbow-list-with-axe li:hover + li + li + li {
background-color: green;
}

.rainbow-list-with-axe li:hover ? li ? li,
.rainbow-list-with-axe li:hover + li + li + li + li {
background-color: blue;
}

.rainbow-list-with-axe li:hover ? li,
.rainbow-list-with-axe li:hover + li + li + li + li + li {
background-color: indigo;
}

.rainbow-list-with-axe:hover ^ body {
background-color: rgba(0,255,0,0.2);
}

/*********************
PRIORITY LIST WITH AXE
*********************/

.priority-list-with-axe li:hover {
font-size: 36px;
background-color: rgba(255,255,255,0.6);
}

.priority-list-with-axe li:hover ? li,
.priority-list-with-axe li:hover + li {
background-color: rgba(255,255,255,0.3);
font-size: 30px;
}

.priority-list-with-axe li:hover ? li ? li,
.priority-list-with-axe li:hover + li + li {
font-size: 24px;
}

.priority-list-with-axe li:hover ? li ? li ? li,
.priority-list-with-axe li:hover + li + li + li {
background-color: rgba(0,0,0,0.3);
font-size: 18px;
}

.priority-list-with-axe li:hover ? li ? li ? li ? li,
.priority-list-with-axe li:hover + li + li + li + li {
background-color: rgba(0,0,0,0.6);
font-size: 12px; 
}

.priority-list-with-axe li:hover ? li ? li ? li ? li ? li,
.priority-list-with-axe li:hover + li + li + li + li + li {
background-color: rgba(0,0,0,0.9);
font-size: 6px; 
}

.rainbow-list-with-axe:hover < div + div ul {
background-color: red;
}

.rainbow-list-with-axe:hover < div ? div ? div ul {
background-color: orange;
}

.rainbow-list-with-axe:hover < div ? div ul {
background-color: green;
}

.priority-list-with-axe:hover < div ? div ? div ? div ul {
background-color: red;
}

.priority-list-with-axe:hover < div ? div ? div ul {
background-color: orange;
}

.priority-list-with-axe:hover < div ? div ul {
background-color: green;
}

.priority-list-with-axe:hover ^ body {
background-color: rgba(255,0,0,0.1);
}

/******************
BOTH LISTS WITH AXE
*******************/

.rainbow-list-with-axe li:hover | li,
.priority-list-with-axe li:hover | li {
color: rgba(255,255,255,0.5);
}

.rainbow-list-with-axe:hover ? h2,
.priority-list-with-axe:hover ? h2 {
color: rgb(223,0,0);
font-size: 22px;
}

.rainbow-list-with-axe:hover < div,
.priority-list-with-axe:hover < div {
border: 1px solid gray;
}

.rainbow-list-with-axe:hover < div | div h2,
.priority-list-with-axe:hover < div | div h2 {
color: gray;
font-size: 12px;
}

.rainbow-list-with-axe:hover < div | div ul,
.priority-list-with-axe:hover < div | div ul {
border:6px dashed rgba(255,255,255,0.4);
}

.rainbow-list-with-axe:hover < div ! div,
.priority-list-with-axe:hover < div ! div {
transform: translateY(72px);
}

.rainbow-list-with-axe:hover < div % div ul,
.priority-list-with-axe:hover < div % div ul {
transform: scale(0.75);
}

.rainbow-list-with-axe:hover \ .axe-info,
.priority-list-with-axe:hover \ .axe-info {
opacity: 1;
}

.rainbow-list-with-axe:hover \ .axe-info {
background-color: rgb(0,91,0);
transform: translateX(184px);
}

.priority-list-with-axe:hover \ .axe-info {
background-color: rgb(191,0,0);
transform: translateX(420px);
}
<p class="axe-info">This list is styled with <strong>axe</strong> &nbsp; &#9658;</p>

<div>
<h2>Rainbow List</h2>
<ul class="rainbow-list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>

<div>
<h2>Priority List</h2>
<ul class="priority-list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>

<div>
<h2><em>axe</em> Rainbow List</h2>
<ul class="rainbow-list-with-axe">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>

<div>
<h2><em>axe</em> Priority List</h2>
<ul class="priority-list-with-axe">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>

<script src="https://rouninmedia.github.io/axe/axe.js"></script>

From Original Post (February 2017)

N.B. I wanted to present this in a StackSnippet, but it isn't hugely straightforward to find and access the stylesheet and the correct part of the CSSOM from the StackSnippet interface, so I am providing a custom link instead.

Example: http://rounin.co.uk/projects/axe/axe2.html

Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 2
    As CSS doesn't have a previous element selector, it might be hard / impossible to do it with just CSS, you would have to use some sort of JavaScript. – MCMXCII Feb 03 '17 at 16:13
  • 1
    Thank you @MCMXCII - that's reassuring. Exactly what I'm hoping for. I'm just waiting for some CSS wizard to come along and say: "Selecting previous elements? That's easy! Just structure HTML and CSS like this..." But I'm hoping instead everyone will echo what you just wrote - which means that **axe** will have some utility. – Rounin Feb 03 '17 at 16:21
  • 2
    See this question for more info on what @MCMXCII was saying: http://stackoverflow.com/questions/1817792/is-there-a-previous-sibling-css-selector. Generally, CSS doesn't provide ways of selecting upwards/backwards. That said, I don't think this is an absolute hard *rule* that the spec authors follow. – Joe Clay Feb 03 '17 at 16:25
  • 3
    Selecting previous elements? That's easy! Just use ACSSSS (Augmented CSS Selector Syntax) or axe for short. :) – Armin Feb 03 '17 at 16:25
  • 1
    Okay, this all looks like good news. Thank you for taking the time to cast your eye over this, everyone. As mentioned above, **axe** requires a little more work, but it will introduce several new non-standard selectors: `?` is the opposite of `+` ; `!` is the opposite of `~` ; `>` is the opposite of `<` and `^` is the opposite of `[SPACE]`. There are two more selectors... and then there is something called _blades_ ... which is going to be really exciting for CSS designers. – Rounin Feb 03 '17 at 16:30
  • 1
    That's some cutting-edge technology. – Armin Feb 03 '17 at 16:34
  • 1
    Something in the line you are going (just in case you didn't know it) https://bigbitecreative.com/a-look-into-writing-future-css-with-postcss-cssnext/ – vals Feb 03 '17 at 21:15
  • That's a useful heads-up, @vals - thank you for that. – Rounin Feb 04 '17 at 11:59
  • 1
    FYI: your solution isn't working because you are requesting the script over an http connection, while SE uses https, it's an unsafe script – Ferrybig Apr 15 '17 at 22:49
  • Spot on, @Ferrybig - after so many different attempts to get the snippet working, the only issue was that I needed to link to the script via an `https:` connection. Thank you very much for the heads up. – Rounin Apr 24 '17 at 12:44

1 Answers1

1

Well, there is a previous element selector, visually speaking, done like this using flexbox and its order property

body > div {
  display: flex;
  flex-direction: column;
}
div div {
  padding: 10px;
  background: lightblue;
}
div div:last-child {
  margin-bottom: 10px;
  order: -1;
}
div div:first-child:hover + div {
  background: lightgreen;
}
<div>
  <div>I'm second, hover me</div>
  <div>I'm first</div>
</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • How useful is this when there are dozens of elements, or in more complex structures? When I first saw this feature I thought it's cool, but I think it's very limited. – Armin Feb 03 '17 at 17:00
  • @Armin When someone wants a CSS only version to select a _previous_ element, it is very useful, though can be hard to maintain if one has a complex structure. – Asons Feb 03 '17 at 17:06
  • Thanks for quick answer. As I said, I already suspected so, but haven't really tested it. @LGSon – Armin Feb 03 '17 at 17:08
  • Good work @LGSon - +1. That's clever thinking to use _flexbox_ `order` to reverse the CSS selector. I'm thinking this would only work with _sibling elements_ though, right? ie. It wouldn't be possible via Flexbox to select a parent element by hovering over a child element? – Rounin Feb 03 '17 at 17:58
  • @Rounin Not directly, though you can put one, or more, extra element inside the parent and use those to indirect mimic being the parent with stuff like background images, borders etc. – Asons Feb 03 '17 at 18:55