Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the colour of text that overlaps an image

The look I'm trying to achieve is if you have black text on a white page, but that text runs into an image. The section of text that is over the image changes it's colour.

I have a 'working' (not flexible) example here using a data attribute to grab the same text and set it on the :before element using content:

https://codepen.io/moy/pen/rNeaGbJ

/* General Shit */

body {
  color: #000;
  font-family: Arial;
  font-size: 1.2rem;
  line-height: 1.5;
}

h2 {
  font-size: 3.6rem;
  margin-bottom: 30px;
}

p {
  margin-bottom: 30px;
}

.btn {
  background: #000;
  color: #fff;
  display: inline-block;
  font-size: 1.2rem;
  padding: 15px 60px;
}

img {
  width: 100%;
  max-width: 100%;
}


/* Grid */

.grid {
  clear: both;
  margin: 0 auto;
  padding: 30px 0;
  max-width: 1000px;
}

.grid__item {
  box-sizing: border-box;
  float: left;
}

.grid--flip .grid__item {
  float: right;
}

.grid__item--caption {
  padding: 30px 60px;
}

.one-half {
  width: 50%;
}


/* Title */

.title-wrap {
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: start;
  justify-content: flex-start;
  margin-left: -60%;
  overflow: hidden;
  position: relative;
}

.grid--flip .title-wrap {
  -webkit-box-pack: end;
  justify-content: flex-end;
  margin-left: 0;
  margin-right: -60%;
}

.title {
  color: #000;
}

.grid--flip .title {
  color: #fff;
}

.title:before {
  color: #fff;
  content: attr(data-title);
  display: block;
  overflow: hidden;
  position: absolute;
  width: 27.75%;
  white-space: nowrap;
}

.grid--flip .title:before {
  color: #000;
  width: 34.75%;
}
<div class="grid">
  <div class="grid__item grid__item--image one-half">
    <img src="http://www.fillmurray.com/800/800" />
  </div>
  <div class="grid__item grid__item--caption one-half">
    <div class="title-wrap">
      <h2 class="title" data-title="Title goes here">Title goes here</h2>
    </div>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <a href="#" class="btn">Shop Collection</a>
  </div>
</div>

<div class="grid grid--flip">
  <div class="grid__item grid__item--image one-half">
    <img src="http://www.fillmurray.com/800/800" />
  </div>
  <div class="grid__item grid__item--caption one-half">
    <div class="title-wrap">
      <h2 class="title" data-title="Title goes here">Title goes here</h2>
    </div>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
    <a href="#" class="btn">Shop Collection</a>
  </div>
</div>

The problem with this is if...

  1. I adjust the width of the container, all the values are off and it looks broken.
  2. the title is longer and wraps onto multiple lines, it is cut off due to the overflow
  3. And why the widths are what they are on the :before element (if someone could explain that'd be great ha)

So I tried a version using px values instead of % which fixes the issues of changing the container width. However I still have the issue of it not behaving right when text wraps onto 2 lines.

Example (using px): https://codepen.io/moy/pen/JjXoMvb

Can anyone think of a better solution for this? Am I overcomplicating this or missing something obvious?

Edit: PX example wrong incorrect, updated link now.

like image 240
user1406440 Avatar asked Oct 27 '25 10:10

user1406440


1 Answers

Use the CSS clip-path property

Example

:root {
  --size: 100px;
}

.resizable {
  border: 2px solid black;
  width: calc(var(--size) * 3);
  height: calc(var(--size) * 2);
  resize: both;
  overflow: auto;
}

.container {
  position: relative;
}

.divider {
  height: 100px;
}

.title {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  margin: 0;
}

img {
  width: var(--size);
  height: var(--size);
}

.left {
  color: blue;
  clip-path: polygon(0 0, var(--size) 0, var(--size) var(--size), 0 var(--size));
}

.right {
  color: red;
  clip-path: polygon(var(--size) 0, 100% 0, 100% 100%, 0 100%, 0 var(--size), var(--size) var(--size));
}

.container-reverse img {
  float: right;
}

.container-reverse .left {
  clip-path: polygon(100% 0, 100% var(--size), calc(100% - var(--size)) var(--size), calc(100% - var(--size)) 0);
}

.container-reverse .right {
  clip-path: polygon(0 0, calc(100% - var(--size)) 0, calc(100% - var(--size)) var(--size), 100% var(--size), 100% 100%, 0 100%);
}

.container-reverse h1 {
  text-align: right;
}
<div class="resizable">
  <div class="container">
    <h1 class="title left">Lorem ipsum dolor sit amet, consectetur adipiscing elit</h1>
    <h1 class="title right">Lorem ipsum dolor sit amet, consectetur adipiscing elit</h1>
    <img src="http://placehold.it/100x100" />
  </div>
  <div class="divider"></div>
  <div class="container container-reverse">
    <h1 class="title left">Lorem ipsum dolor sit amet, consectetur adipiscing elit</h1>
    <h1 class="title right">Lorem ipsum dolor sit amet, consectetur adipiscing elit</h1>
    <img src="http://placehold.it/100x100" />
  </div>
</div>
like image 73
Jannes Carpentier Avatar answered Oct 29 '25 00:10

Jannes Carpentier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!