I'm new to web development and as my first project, I'm designing a visualization of projects I'm working on which I'd like to look like this:
I'm having a hard time centering the star in each row. This is the current code looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Amarante&display=swap">
<style>
body {
background-color: #124264;
color: #000000;
font-family: 'Amarante';
margin: 0;
/*display: flex;
align-items: center;
justify-content: flex-end; /* Adjusted alignment to right */
height: 100vh;
overflow: auto;
}
/* Style for the first image */
.starImages {
width: 90px; /* Set the desired width */
height: auto; /* Maintain aspect ratio */
vertical-align: middle; /* Align the star icon with text */
}
/* Remove bullet points from the list */
#projectNamesList {
list-style: none;
display: grid; /* Use grid display */
grid-template-columns: 1fr; /* One column for each item */
/*align-items: flex-end; /* Align items to the right */
padding: 0; /* Remove default padding */
overflow-x: auto; /* Allow horizontal scrolling */
/*justify-items: flex-end; /* Align items to the right */
justify-items: center;
}
/* Style for individual list items */
.projectItem {
display: flex;
align-items: center;
white-space: nowrap; /* Prevent line breaks within items */
position: relative; /* Position relative for adding line */
}
/* Add a gold line */
.thinLine {
position: relative;
height: 2px;
background-color: #E0B624;
margin-left: 0px;
}
.thickLine {
position: relative;
height: 10px;
background-color: #E0B624;
z-index: -1
}
</style>
</head>
<body>
<ul id="projectNamesList"></ul>
<script>
async function fetchData() {
try {
const response = await fetch('https://us-central1-project-organization-noa.cloudfunctions.net/getData'); // Cloud Function URL
console.log(response);
const data = await response.json();
console.log(data);
const projectNamesList = document.getElementById('projectNamesList');
dataWithoutHeader = data.slice(1);
dataWithoutHeader.forEach(row => {
const listItem = document.createElement('li');
listItem.classList.add('projectItem'); // Add the class for styling
// Create a span for the project name
const projectNameSpan = document.createElement('span');
projectNameSpan.textContent = row[0];
// Create an image element for the star icon
const starIcon = document.createElement('img');
starIcon.src = 'star.svg';
starIcon.alt = 'Star';
starIcon.classList.add('starImages');
// Create the gold line element
const thickLine = document.createElement('div');
thickLine.classList.add('thickLine');
daysSince = row[2];
numericThickWidth = 7 * Math.sqrt(daysSince)
thickWidth = numericThickWidth + 'px';
thickLine.style.width = thickWidth;
percent = row[5] / 100;
thinWidth = numericThickWidth * ((1 / percent) - 1) + 'px';
//thinWidth = parseInt();
const thinLine = document.createElement('div');
thinLine.classList.add('thinLine');
thinLine.style.width = thinWidth;
projectNameSpan.style.marginRight = - numericThickWidth + 'px';
// Append the elements to the list item
listItem.appendChild(projectNameSpan);
listItem.appendChild(thickLine);
listItem.appendChild(starIcon);
listItem.appendChild(thinLine);
projectNamesList.appendChild(listItem);
});
// Center scroll
const halfWidth = projectNamesList.scrollWidth / 2;
const halfViewport = window.innerWidth / 2;
projectNamesList.scrollLeft = halfWidth - halfViewport;
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
</script>
</body>
</html>
Here is what the website looks like now with uncentered stars:
Things I've tried:
Thank you for any pointers you can give!
I would use a three-column grid to achieve this layout, with the left column containing the thick line and the title, the centre column containing the star, and the right column containing the thin line.
The other key to making it work is that grids don’t have row elements with nested cell elements like tables do, they only have child elements. Your grid (a style on the <ul>
element) needs its child elements to be the children of your <li>
elements, not the <li>
elements themselves. Use display: contents
on the <li>
elements to achieve this.
#projectNamesList {
display: grid;
grid-template-columns: auto 30px auto;
}
.projectItem {
display: contents;
}
A working snippet to demonstrate:
async function fetchData() {
try {
const response = await fetch('https://us-central1-project-organization-noa.cloudfunctions.net/getData'); // Cloud Function URL
console.log(response);
const data = await response.json();
console.log(data);
const projectNamesList = document.getElementById('projectNamesList');
dataWithoutHeader = data.slice(1);
dataWithoutHeader.forEach(row => {
const listItem = document.createElement('li');
listItem.classList.add('projectItem'); // Add the class for styling
// Create a span for the project name
const projectNameSpan = document.createElement('span');
projectNameSpan.textContent = row[0];
// Create an image element for the star icon
const starIcon = document.createElement('img');
starIcon.src = 'https://mario.wiki.gallery/images/b/bb/MPS_Favicon.svg';
starIcon.alt = 'Star';
starIcon.classList.add('starImages');
// Create the gold line element
const thickLine = document.createElement('div');
thickLine.classList.add('thickLine');
daysSince = row[2];
numericThickWidth = 7 * Math.sqrt(daysSince)
thickWidth = numericThickWidth + 'px';
thickLine.style.width = thickWidth;
percent = row[5] / 100;
thinWidth = numericThickWidth * ((1 / percent) - 1) + 'px';
//thinWidth = parseInt();
const thinLine = document.createElement('div');
thinLine.classList.add('thinLine');
thinLine.style.width = thinWidth;
const lineWithTitle = document.createElement('div');
lineWithTitle.classList.add('lineWithTitle');
// Append the elements to the list item
lineWithTitle.appendChild(thickLine);
lineWithTitle.appendChild(projectNameSpan);
listItem.appendChild(lineWithTitle);
listItem.appendChild(starIcon);
listItem.appendChild(thinLine);
projectNamesList.appendChild(listItem);
});
} catch (error) {
console.error('Error fetching data:', error);
}
}
fetchData();
body {
background-color: #124264;
color: #000000;
font-family: 'Amarante';
margin: 0;
height: 100vh;
overflow: auto;
}
.starImages {
width: 100%;
}
#projectNamesList {
list-style: none;
display: grid;
grid-template-columns: auto 30px auto;
align-items: center;
}
.projectItem {
display: contents;
}
.lineWithTitle {
text-align: right;
position: relative;
}
.thickLine {
height: 10px;
background-color: #E0B624;
margin: 0 0 0 auto;
}
.thickLine+span {
position: absolute;
right: 0;
top: -5px;
}
.thinLine {
height: 2px;
background-color: #E0B624;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Amarante&display=swap">
<ul id="projectNamesList"></ul>