1

I'm building a personal website using Kirby CMS. I have a nav menu that automatically adds new buttons for any new pages I create for the website. I would like each button to have a background color that is randomly chosen from an array of colors every time you load the page.

I've been using the following code:

This is the snippet that loads the javascript and generates the buttons for navigation.

<html>
    <head>
            <title><?= $site->title()?></title>
            <meta name="viewport" content="width=device-width, initial-scale1.0">
            <meta  charset="UTF-8">
            <?= css('/assets/css/menu.css')?>
            <?= js('assets/js/script.js')?>
            <link rel="preconnect" href="https://fonts.googleapis.com">
            <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
            <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@500;700;900&display=swap" rel="stylesheet">
    </head>
    <body class="blog_content_container">
            <img class="background_overlay" src="<?= url('assets/svg/background_overlay.svg') ?>">
            <header class="header">
                    <nav class="menu">
                            <img class="logo_header" src="<?= url('assets/svg/logo.svg') ?>">
                            <?php foreach ($site->children()->listed() as $childpage): ?>
                                    <button class="menu_item">
                                            <a href="<?= $childpage->url()?>" class="menu_text" >
                                                    <?= $childpage->title() ?>
                                            </a>
                                    </button>
                            <?php endforeach ?>
                    </nav>
            </header>

This is the Javascript I have written that is supposed to pick colors from an array and apply it to the buttons.

window.onLoad = () => {
    var colors = ['#ffffff', '#ffbd4b', '#ff634b', '#4b9fff'];
    var random_color = colors[Math.floor(Math.random() * colors.length)];
    document.getElementsById('menu_item').style.backgroundColor = random_color;
};

Finally, this is the CSS that I have written.

.menu {
    grid-column: 2;
    grid-row: 1;
    display: flex;
    flex-flow: row wrap;
    align-items: center;
}

.menu_item {
    width: 150px;
    height: 50px;
    border: 6px solid #FFFFFF;
    border-radius: 6px;
    box-shadow: 4px 4px 6px rgba(0, 0, 0, 0.65);
    margin: 1rem;
    cursor: pointer;
}

.menu_item:hover {
    transform: scale(1.1);
}

.menu_text{
    font-family: 'nunito', sans-serif;
    font-size: 1.4rem;
    font-weight: 900;
    color: rgb(255, 255, 255);
    text-decoration: none;
}

Everything loads as expected without throwing errors, but no background colors apply to the buttons. I appreciate any help you can give, I'm a beginner so please be nice :)

AveryH
  • 41
  • 5
  • 1
    `menu_item` is a `class` not an `id`. So you should use `querySelector('.menu_item')` instead of `getElementsById('menu_item')` -> If that solves your issue, please remove your question voluntarily as it is caused by a typo. PS: There is also no `getElementsById` in JS as an ID has to be unique. Therfore only a `getElementById` exsist – tacoshy May 21 '22 at 21:52
  • Hi thank you for the help, I've changed it to `document.querySelector('.menu_item').style.backgroundColor = random_color;` but still not functioning unfortunately. Again thank you. – AveryH May 21 '22 at 22:05
  • 1
    I found another typo: `onLoad` instead of `onload`. If I change the typo in a script it works for me: https://codepen.io/tacoshy/pen/VwQzvXK – tacoshy May 21 '22 at 22:14
  • For each iteration of the loop a button is generated as `` I don't get any errors. – AveryH May 21 '22 at 22:24
  • Oh i'll change that typo and try! – AveryH May 21 '22 at 22:27
  • PS: Anchor inside a button is invalid (HTML Markup) aswell. Either you need a button (trigger for a script) or an anchor (directing to another resource). If you need to combine both, you should add an `eventListener` or `onclick`-trigger to the anchor. – tacoshy May 21 '22 at 22:27
  • I tried changing the typo too but no dice :( – AveryH May 21 '22 at 22:32
  • You can visit the page at https://hire-avery.com/ is that helps. – AveryH May 21 '22 at 22:37
  • I've got it functioning now actually, but it only applies to the first button generated and not each button. So that's given me a new direction to go troubleshooting now, thank you! – AveryH May 21 '22 at 22:52
  • thats because you need to loop over all the buttons as `querySelector` aswell as `getElementById` selects only the first element. You can use: `document.querySelectorAll('.menu_item').forEach(el => el.style.backgroundColor = random_color);` However this again will apply the same color to every button. Alternativly you have to move the randomizer inside the `forEach` function. – tacoshy May 21 '22 at 22:56

1 Answers1

0

Since the question is way more complex then the few typos I will revert to an answer now instead of keeping an extented conversation within the comments.

First there are a few typos:

  1. getElementsById does not exsist. Naturally an id has to be unique and as such can onyl exsist once. So it has to be getElementById
  2. The above mentioned typo does not matetr in the first palce as it is a wrong call. The called element has a class with that name and not an id so querySelector should be chosen.
  3. onLoad actually causes an error and has to be written onload
  4. If you fix all those typos the script will actually work. However it will only apply to the first element with that class. To apply it to all Elements the querySelectorAll has to be used and be combined with forEach
  5. That will lead us to the next issue that. The random color will be for all elements the same unless we move the randomizer within the forEach function:

window.onload = () => {
  var colors = ['#ffffff', '#ffbd4b', '#ff634b', '#4b9fff'];
  document.querySelectorAll('.menu_item').forEach(
    el => el.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)]);
};
/* for visualisation purpose only */
div {
  padding: 10px;
  text-align: center;
  margin-bottom: 5px;
  border: 2px dashed red;
}
<div class="menu_item">1</div>
<div class="menu_item">2</div>
<div class="menu_item">3</div>
<div class="menu_item">4</div>
<div class="menu_item">5</div>
tacoshy
  • 10,642
  • 5
  • 17
  • 34
  • Thank you so much! I've fixed everything and now it's working. You helped me understand how it all functions better. – AveryH May 21 '22 at 23:23
  • great to hear, I just noticed another issue you havign now. Within your array you have `#FFFFFF` as color. IF that is used as background color then your button will be unreadable as your font-color is white aswell. Either you need to change the font-color or remove/change the white background-color from the array. – tacoshy May 21 '22 at 23:26
  • I was able to do that one on my own! It will pick a nonwhite color for the text and border if the background is white. – AveryH May 23 '22 at 03:55