22

I'm trying to style my element with pseudo-class and pseudo-element. like hover::before is working perfectly but :visited::before is not working.

enter image description here

I want to show "Seen" if link is visited but :visited::before isn't working.

*, *:before, *:after {
        box-sizing: border-box;
    }
    body {
        background-color: #eee;
        font-size: 23px;
        padding: 50px;
        font-family: 'Ubuntu Condensed', sans-serif;
    }
    .style-3 {
        margin: 20px;
        float: left;
        padding: 20px 80px 20px 20px;
        border: 1px solid #ccc;
        background-color: #fff;
        position: relative;
        text-decoration: none;
    }
    .style-3 {
        color: green;
    }
    .style-3:visited {
        color: red;
    }
    .style-3:hover::before {
        content: "Hover";
        position: absolute;
        right: 20px;
        color: yellow;
    }
    .style-3:visited::before {
        content: "Seen";
        position: absolute;
        right: 20px;
        color: blue;
    }
<a href="#1" class="style-3">Seen Effects</a>
<a href="#2" class="style-3">Seen Effects</a>
<a href="#3" class="style-3">Seen Effects</a>
Usman Arshad
  • 868
  • 8
  • 19

4 Answers4

13

It may be possible, but don't take it for granted. According to the spec,

Note: It is possible for style sheet authors to abuse the :link and :visited pseudo-classes to determine which sites a user has visited without the user's consent.

UAs may therefore treat all links as unvisited links, or implement other measures to preserve the user's privacy while rendering visited and unvisited links differently.

Inserting content can change the size of the element, so it would be trivial to detect this and know if the user has visited some sites. Therefore, most browsers won't allow you to do so.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Apparently as for 2013, it was still possible on Opera, not sure for now? http://stackoverflow.com/questions/16180422/cannot-change-the-content-of-visited-before-pseudo-elements – A. Wolff Jun 15 '15 at 17:43
  • 1
    I think UA still show visited links in different colors. However, modern UAs block JavaScript code from determining the color of links i.e. any JavaScript code cannot distinguish between computed colors of visited and unvisited links. – Salman A Jun 24 '15 at 18:53
  • @SalmanA True, but the difference is that lying about the color is usually not problematic. But inserting content can modify the widths and the positions of lots of elements, and lying about that could break JS code that rely on those values. – Oriol Jun 24 '15 at 19:52
10

Mozilla Developer Network :visited says

Note: For privacy reasons, browsers strictly limit the styles you can apply using an element selected by this pseudo-class: only color, background-color, border-color, border-bottom-color, border-left-color, border-right-color, border-top-color, outline-color, column-rule-color, fill and stroke.

Idea 1: create child element and write CSS for it

<a href="#1" class="style-3">Seen Effects<span>Seen</span></a>
<a href="#2" class="style-3">Seen Effects<span>Seen</span></a>
<a href="#3" class="style-3">Seen Effects<span>Seen</span></a>

*, *:before, *:after {
    box-sizing: border-box;
}
body {
    background-color: #eee;
    font-size: 23px;
    padding: 50px;
    font-family: 'Ubuntu Condensed', sans-serif;
}
.style-3 {
    margin: 20px;
    float: left;
    padding: 20px 20px 20px 20px;
    border: 1px solid #ccc;
    background-color: #fff;
    position: relative;
    text-decoration: none;
}
.style-3 {
    color: green;
}
.style-3:visited {
    color: red;
}
.style-3 span{
    color: #fff;
    margin-left: 20px;
}
.style-3:visited span{
    color: #ccc;
    margin-left: 20px;
}

Fiddle https://jsfiddle.net/ZigmaEmpire/do8yeLm1/

Idea 2: create a transparent background image with text matching the background color, and change the background color for :visited (not recommended)

Dickens A S
  • 3,824
  • 2
  • 22
  • 45
5

It is easy, if you have a span next to it:

*, *:before, *:after {
  box-sizing: border-box;
}
body {
  background-color: #eee;
  font-size: 23px;
  padding: 50px;
  font-family: 'Ubuntu Condensed', sans-serif;
}
.seen {
  margin: 20px;
  float: left;
  padding: 20px 20px 20px 20px;
  border: 1px solid #ccc;
  background-color: #fff;
  position: relative;
  text-decoration: none;
}
.seen {
  color: green;
}
.seen:visited {
  color: red;
}
.seen + span {
  color: #fff;
  margin-left: 20px;
}
.seen:visited + span {
  color: #ccc;
  margin-left: 20px;
}
<a href="#1" class="seen">Seen Effects</a> <span>Seen</span>
<a href="#2" class="seen">Seen Effects</a> <span>Seen</span>
<a href="#3" class="seen">Seen Effects</a> <span>Seen</span>

This doesn't work in Chrome, but works in Chromium!

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
  • So this is essentially the same answer as [zigma empire's answer](http://stackoverflow.com/a/30859682) except that you are using `+` combinator instead of space combinator. – Salman A Jun 25 '15 at 07:14
  • @SalmanA Yes, but this doesn't need the markup to have nested tags. That's one of the advantages of this approach! `:D` – Praveen Kumar Purushothaman Jun 25 '15 at 07:41
1

Try utilizing className to apply visited class , css :before properties to clicked a elements; localStorage to store hash of clicked a.style-3 elements. If a.style-3 element clicked, maintain visited class using stored hash within localStorage.visited

$(function() {
  // if `localStorage.visited` `undefined`, 
  // set `localStorage.visited` to array as string
  if (!localStorage.visited) {
    localStorage.setItem("visited", "[]");
  } else {
    // get `localStorage.visited` as array
    var visited = JSON.parse(localStorage.getItem("visited"));
    // iterate `visited` array of `hash` items,
    // set `visited` `class` at `a.style-3` elements having
    // `hash` stored within `visited`
    visited.forEach(function(link, index) {
      $("a.style-3[href$='" + link + "']").addClass("visited");
    });
  };

  $("a.style-3").on("click", function(e) {
    if (!/visited/.test(e.target.className)) {
      $(e.target).addClass("visited");
      var visits = JSON.parse(localStorage.getItem("visited"));
      // if `hash` not within `visits` , push `hash` to `visits`
      if (visits.indexOf(e.target.hash) === -1) {
        visits.push(e.target.hash);
        localStorage.setItem("visited", JSON.stringify(visits));
      };
    }
  });

});
*, *:before, *:after {
        box-sizing: border-box;
    }
    body {
        background-color: #eee;
        font-size: 23px;
        padding: 50px;
        font-family: 'Ubuntu Condensed', sans-serif;
    }
    .style-3 {
        margin: 20px;
        float: left;
        padding: 20px 80px 20px 20px;
        border: 1px solid #ccc;
        background-color: #fff;
        position: relative;
        text-decoration: none;
    }
    .style-3 {
        color: green;
    }
    .style-3.visited {
        color: red;
    }
    .style-3:hover:before {
        content: "Hover";
        position: absolute;
        right: 20px;
        color: yellow;
    }
    .style-3.visited:before {
        content: "Seen";
        position: absolute;
        right: 20px;
        color: blue;
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<a href="#1" class="style-3">Seen Effects</a>
<a href="#2" class="style-3">Seen Effects</a>
<a href="#3" class="style-3">Seen Effects</a>
guest271314
  • 1
  • 15
  • 104
  • 177
  • :visited works even page refresh that link is visited, in your case after refreshing page links are getting reset... is it possible to detect via java that if link is visited then add class? – Usman Arshad Jun 21 '15 at 10:54
  • @UsmanArshad See updated post; added portion utilizing `localStorage` to save `hash` of visited links, apply `visited` `class` to `a.style-3` elements that have been previously clicked, where the `hash` of clicked element stored at `localStorage` – guest271314 Jun 21 '15 at 14:52
  • @UsmanArshad Note, substitute `sessionStorage` for `localStorage` to clear items when browsing session ends, see https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage – guest271314 Jun 21 '15 at 14:59