0
\$\begingroup\$

I'm working on a proof of concept idea I want to use in a Brutalist styled web page.

This would involve having transparent image being placed randomly behind the content on load, I have this working with mostly vanilla JS, minus a few jQuery methods that I wasn't sure how I could translate back to vanilla. (I learned jQuery helper functions before having a concrete understanding of vanilla JS and now I regret it. lol)

Anyways, here's the JS Fiddle, for you to see the concept, and below is the code with comments.

Javascript

/* Set Variables at the start of the document *
*
* Frame = Parent of the image element (absolute pos within body content) *
* Top/Left Position = the top/left walls of the document *
* Tag = variable for Image element *
*/

var frame = document.getElementById("frame");
var top_position = (Math.random() * ($(document).width() - 500)).toFixed();
var left_position = (Math.random() * ($(document).width() - 500)).toFixed();
var tag = document.getElementById('random');

// Create array of images to randomly select one
var image = [];
image[0] = "https://via.placeholder.com/350x150";
image[1] = "https://via.placeholder.com/150x150";
image[2] = "https://via.placeholder.com/150x350";
image[3] = "https://via.placeholder.com/500x150";
var size = image.length

// randomly selects number of array 0 through size(array.length)
var x = Math.floor(size * Math.random());

//Apply image src/styles to image on load
tag.src = image[x];
tag.style.position = 'absolute';
tag.style.top = top_position + "px";
tag.style.left = left_position + "px";
top_position += 20;
left_position += 20

Is there anyways I can simplify this and combine some functions, while still keeping it readable?

Example of the effect I was trying to implement

multiple images, within grids

\$\endgroup\$
1
\$\begingroup\$

Here's an alternate implementation using background

const image = [
  "https://via.placeholder.com/350x150",
  "https://via.placeholder.com/150x150",
  "https://via.placeholder.com/150x350",
  "https://via.placeholder.com/500x150"
]
const randomImage = image[Math.floor(image.length * Math.random())]

const stuff = document.getElementById("stuff")
const stuffStyles = window.getComputedStyle(stuff)
const width = stuffStyles.getPropertyValue('width').slice(0, -2)
const height = stuffStyles.getPropertyValue('height').slice(0, -2)
const top = Math.floor(Math.random() * height)
const left = Math.floor(Math.random() * width)

// Ensure no-repeat is styled in your CSS
stuff.style.backgroundImage = `url(${randomImage})`
stuff.style.backgroundPosition = `${left}px ${top}px`

Few key things why this might be a better option:

  • It does not require dummy markup.
  • No z-index issues.

Also, there's a few more things changed:

  • You can get window.getComputedStyle() to grab the current styles of any element.
  • Try avoiding decimals as pixel values. This causes blurring of edges in some browsers. Floor the values after all the calculations have been performed.
\$\endgroup\$
  • \$\begingroup\$ Sorry for the late reply, wanted to go back through a Team treehouse lesson to make sure I was understanding the use of const. This seems to work pretty well, but I don't recall a way to tone the opacity of the background image without also toning down the text and content. Unless I style it as an :after? \$\endgroup\$ – knocked loose Sep 21 '18 at 14:37
1
\$\begingroup\$

Yes, I love using functions to make code more readable.

First lets get rid of your jQeury, simply replace $(document) with document.body.clientWidth.

Lets create a function to get an image.

function getImage(src, top, left) {
  var imgElement = document.createElement("img");
  imgElement.src = src;
  imgElement.style.top = top + 'px';
  imgElement.style.left = left + 'px';
  imgElement.style.position = 'absolute';
  imgElement.style.opacity = '.3';

  return imgElement;
}

Notice we are creating a new image element, not modifying an existing one. This has two advantages:

  1. Avoid slow dom minipulaiton
  2. Call multiple times to add multiple images.

Now lets use this function in random picture function

function randomPicture() {
  var randomIndex =  Math.floor((image.length) * Math.random());
  var left_position = (Math.random() * maxWidth).toFixed();
  //Assume you wanted height and not width
  var top_position = (Math.random() * maxHeight).toFixed();
  var imgEl = getImage(image[randomIndex], top_position, left_position);
  contentEl.appendChild(imgEl);
}

Notice we use appendChild

Other suggestions:

  • Avoid magic numbers, use constants
  • Avoid variable hoisting
  • Use meaningful variable names
  • Simplify calculations with constants

var MAX_IMAGE_WIDTH = 500; // repalce magic number with const
var MAX_IMAGE_HEIGHT = 350;   // repalce magic number with const
var docWidth = document.body.clientWidth;  //replace $(document).width()
var docHeight = document.body.clientHeight || 500;  //Note: document.body.clientHeight returns 0 in this envorment, in browser will be actaul height, setting defalult value of 500  
// prevent negitve values that could place your image off screen
var maxWidth = Math.max(0, docWidth - MAX_IMAGE_WIDTH); 
var maxHeight = Math.max(0, docHeight - MAX_IMAGE_HEIGHT); 
var contentEl = document.getElementById('content');
var image = [ //set innital values and prevent variable hoisiting 
  "https://via.placeholder.com/350x150",
  "https://via.placeholder.com/150x150",
  "https://via.placeholder.com/150x350",
  "https://via.placeholder.com/500x150"
];

function getImage(src, top, left) {
  var imgElement = document.createElement("img");
  imgElement.src = src;
  imgElement.style.top = top + 'px';
  imgElement.style.left = left + 'px';
  imgElement.style.position = 'absolute';
  imgElement.style.opacity = '.3';
  
  return imgElement;
}

function randomPicture() {
  var randomIndex =  Math.floor((image.length) * Math.random());
  var left_position = (Math.random() * maxWidth).toFixed();
  //Assume you wanted height and not width
  var top_position = (Math.random() * maxHeight).toFixed();
  var imgEl = getImage(image[randomIndex], top_position, left_position);
  contentEl.appendChild(imgEl);
}

randomPicture();
randomPicture();
randomPicture();
.left {
  width: 14%;
}

.right {
  width: 84%;
  border-left: none !important;
  overflow: hidden;
}

.left,
.right {
  display: block;
  float: left;
  border: 1px solid #000;
  margin: 0;
  height: 500px;
}

.content-body {
  position: relative;
}

#frame {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  height: 100vh;
  width: 100%;
}

#random {
  opacity: .3;
}

.content {
  padding: 30px 40px;
  overflow: scroll;
  display: block;
}

h1 {
  font-size: 90px;
  padding: 0;
  margin: 0;
}

h2 {
  margin: 3px 0;
}
<div class="left">
  <ul>
    <li><a href="home">Home</a></li>
    <li><a href="Inspo">Inspo</a></li>
    <li><a href="shop">Shop</a></li>
  </ul>
</div>
<div class="right">

  <div class="content" id='content'>
    <div class="header">
      <h1>Challenger</h1>
      <h2>This is the race.</h2>
    </div>

    <div class="content-body">
      <h4>On my mark...</h4>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin aliquet pharetra pharetra. Aliquam mauris leo, blandit vitae vulputate sit amet, imperdiet non magna. Pellentesque gravida gravida dapibus. Vivamus augue neque, dignissim sed bibendum
        non, malesuada sed orci. Nam turpis mi, dictum ac ullamcorper sit amet, ornare nec sapien. Pellentesque at nibh vel lectus porta sodales. Vestibulum malesuada, urna a egestas iaculis, velit neque vehicula nunc, quis tincidunt libero est eget arcu.
        Phasellus in nisl lectus. Curabitur tellus elit, lobortis eget viverra non, tempor eu quam. Duis facilisis dictum nulla, sit amet aliquet augue viverra eget. Curabitur elit tellus, luctus ac pretium et, tristique at enim.</p>

      <p> Morbi gravida vel orci et fringilla. Vestibulum id lorem vel ipsum tincidunt vehicula gravida eget ipsum. Donec feugiat nisl arcu, non consectetur lacus porttitor ac. Morbi et quam et risus suscipit maximus sit amet eu quam. Aliquam non felis dictum,
        porta dolor quis, suscipit nisl. Suspendisse id nulla et odio rutrum convallis. Pellentesque consequat quis ante id sodales. Nam porttitor nulla velit, non sodales diam dignissim ac.</p>

      <p> Sed quis pretium purus, sed tempor arcu. Duis non sapien sed sem posuere dignissim. Sed id dui ipsum. Nam aliquam, arcu at lacinia scelerisque, justo dui tristique odio, et sodales lorem ante in enim. Orci varius natoque penatibus et magnis dis
        parturient montes, nascetur ridiculus mus. Morbi dictum varius quam a congue. Nulla ornare elit quis ante ullamcorper, vitae vestibulum nunc condimentum. Sed dignissim erat vel lacus pulvinar, sit amet maximus lectus varius. Vestibulum ante ipsum
        primis in faucibus orci luctus et ultrices posuere cubilia Curae; Phasellus convallis, turpis ut molestie ultricies, lacus enim convallis mi, quis mollis arcu est vitae mauris. Donec quis tortor eu elit aliquam tincidunt. Sed vel sollicitudin
        justo.
      </p>

      <div id="frame">
        <img id="random" />
      </div>
    </div>
  </div>
</div>

References:

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.