Bruno De Faria
Bruno De Faria

Reputation: 179

Trouble getting the right CSS selector

I'm having trouble getting the right selector.

Let me try to explain the best way I can:

I'm working on a project that I cannot change HTML and Javascript, it has some dynamic HTML and other reasons.

On the project, there is an image on a <img> tag.

However, I need to change colors between two layouts, and as you can see on the HTML/CSS the only way I got that to work is to hide th <img> tag and set a background to the anchor, that has a title.

So, now, when I change the layouts, the image changes, however there is also something else, this image on click hides the menu and changes the image one more time.

Now, I need to hide the background on the anchor when the title on the image changes.

Here is the HTML BEFORE clicking the image

<div id="div-mh-ico">

<ul id="ul-icone-mh" class="icones">
    <li>
        <a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
            <img title="Esconder menu horizontal" id="imgHideMenu" src="images/ico_hidemh.png" width="16" height="16">
        </a>
    </li>
</ul>

And here is the HTML AFTER I click on the image

<div id="div-mh-ico">

<ul id="ul-icone-mh" class="icones">
    <li>
        <a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
            <img title="Exibir menu horizontal" id="imgHideMenu" src="images/ico_showmh.png" width="16" height="16">
        </a>
    </li>
</ul>

THE CSS

I HIDE THE ORIGINAL IMAGE, USED ON THE OTHER LAYOUT

#ul-icone-mh li a img {
    visibility: hidden !important;
}

AND SET THE NEW IMAGE

a[title="Esconder menu horizontal"] {
box-sizing: border-box;
background-image: url(../images/ico_hidemhc.png);
background-size: 16px;
background-repeat: no-repeat;
}

And when I click it, the image stays the same, but I need to hide that image when the title changes and add another image.

Any ideas what I can do?

Upvotes: 0

Views: 110

Answers (3)

Alohci
Alohci

Reputation: 82976

You need a bit more than just the right CSS selector. The problem there is the old stumbling block that there is no parent selector.

A bit more thought and work is required.

img { height:50px; width:50px }

ul {padding: 0; list-style:none;}

.icones a::after {
  content: '';
  height:50px; width:100px;
  background-image: linear-gradient(to right, #00FF00 50%, #0000FF 50%); 
  display:inline-block;
}

.icones a {
  height:50px; width:50px;
  display:block;
  white-space:nowrap;
  overflow:hidden;
  font-size:0;
}
.icones a img[title='Esconder menu horizontal'] {
  margin-left: -50px;
}

.icones a img[title='Exibir menu horizontal'] {
  margin-left: -100px;
}
  <div id="div-mh-ico">
    <ul id="ul-icone-mh" class="icones">
        <li>
            <a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
                <img title="Esconder menu horizontal" id="imgHideMenu" src="http://placehold.it/200/ff0000" width="16" height="16">
            </a>
        </li>
    </ul>
  </div>
  <div id="div-mh-ico">
    <ul id="ul-icone-mh" class="icones">
        <li>
            <a href="#" class="mh-icon" title="Esconder menu horizontal" onclick="hideMenuHorizontal();">
                <img title="Exibir menu horizontal" id="imgHideMenu" src="http://placehold.it/200/990000" width="16" height="16">
            </a>
        </li>
    </ul>
  </div>

Here I've increased the images to 50x50px from 16x16px to make them a bit easier to see but the principle is just the same.

For the two images referenced by the HTML, I've used two blocks that are different shades of red.

For the two CSS overlay images, for simplicity I've used a linear gradient making a block that's the height of the image and twice the width. The left half is green and the right half blue. You would use a sprite for the two images you want to display. The left half of the sprite would contain the "Esconder ..." replacement image and the right half of the sprite would contain the "Exibir ..." replacement image.

I've also shown both cases together rather than switching between them on click, again for simplicity.

The idea is that the left margin of the image is made negative to shift it out of the a element. The pseudo element that follows contains the sprite and is shifted into that space, either by the width of the image, or twice the width of the image to show different contents for the two cases.

Hence we get a green box for the "Esconder ..." case and a blue box for the "Exibir ..." case.

Upvotes: 1

Bricky
Bricky

Reputation: 2745

It's not very clear what you're trying to accomplish, but if you're trying to change the anchor based on the image, this is simply not possible using CSS alone.

You can target child elements based on their parents, but you can not target parent elements based on their children in CSS (currently).

The only way to do this would be to affect how the HTML renders the two options, or using Javascript.

There are a few different suggested specs for such a selector, but none have yet been implemented.

Since the img tag is what has the dynamic title, that is the only thing you will be able to target with your CSS. If you cannot accomplish your task by targeting the img then it can't be done within the constraints you stated.

Selectors: https://www.w3.org/TR/CSS2/selector.html

Support for the proposed spec for a parent selector: https://caniuse.com/#feat=css-has

Upvotes: 0

Roddy of the Frozen Peas
Roddy of the Frozen Peas

Reputation: 15186

So if I understand correctly, then the title is "esconder", you want to hide the default image and inject your own. And otherwise you want to show the original (when the title is "exibir".)

You have correctly identified how you would target the a tag based on the title: a[title="Esconder menu horizontal"]. What you then need to do is only exclude the image when it is inside of this tag, and then replace it with your own image. You then also need to give it an explicit size, and declare the a tag which now directly has the background image with some size. Like so:

a[title="Esconder menu horizontal"] img { display: none; }
a[title="Esconder menu horizontal"] {
  box-sizing: border-box;
  background-image: url(../images/ico_hidemhc.png);
  background-size: 16px;
  background-repeat: no-repeat;
  height: 16px;
  width: 16px;
  display:inline-block;
}

You will notice I added a few lines to your existing styling:

  • display:inline-block tells the browser that this element should follow the flow like an inline element, but should have block-type semantics. By default, an anchor tag is an inline element, which means it doesn't have explicit size or width -- just what is enforced by its children. Since you've delcared that the child is not to be seen, the anchor tag effectively collapses to be of 0x0 size.
  • height:16px; width:16px tells the browser the size you want for this image. I guessed at these dimensions based on the background-size property you had set. Since we've told the browser using the display property that this element has explicit size, we now tell it what that size is.

Upvotes: 0

Related Questions