Aligning the stars with CSS

One of the components I have deals with a star rating system, and I thought it would be cool to use Font Awesome icons for half stars. Everything is working well except for the CSS styling aspect. While I managed to position some of the stars correctly by flipping them (Font Awesome icons can only span in one direction), they are not touching as desired. Any suggestions on the most straightforward way to address this issue?

Rater.js

import React, { useState } from 'react'
import {FaStarHalf} from "react-icons/all";
import './Rater.css'


const Rater = () => {
    const [rating, setRating] = useState(null);
    const [hover, setHover] = useState(null);
    const [value] = useState(100);
    const [iconValue, setIconValue] = useState(5);

    return (
        <div>
            <select
                onChange={e => {
                    setIconValue(Number(e.target.value));
                }}
            >
                {Array.from(new Array(value), (value, index) => index + 1).map(
                    value => (
                        <option key={value} value={value}>
                            {value}
                        </option>
                    )
                )}
            </select>
            <h1> Select Amount of Icons </h1>

            {[...Array(iconValue), ...Array(iconValue)].map((icon, i) => {
                const value = i + 1;

                return (
                    <label>
                        <input
                            type="radio"
                            name="rating"
                            value={value}
                            onClick={() => setRating(value)}
                        />
                        <FaStarHalf
                            className={i % 2 ? "star-left" : "star"}
                            color={value <= (hover || rating) ? "#ffc107" : "#e4e5e9"}
                            size={100}
                            onMouseEnter={() => setHover(value)}
                            onMouseLeave={() => setHover(null)}
                        />
                    </label>

                );
            })}
        </div>
    );
};

export default Rater

Rater.css

input[type='radio'] {
    display: none;
}

.star {
    cursor: pointer;
    transition: color 200ms;
    /*transform: rotate(180deg);*/
}
.star-left {
    cursor: pointer;
    transition: color 200ms;
    transform: scaleX(-1);
}

Answer №1

If you're looking to neatly align elements, consider using flexbox.

All you need to do is enclose your stars within a container:

<div class="container">
  <div class="star"></div>
  <div class="star"></div>
  <div class="star"></div>
  <div class="star"></div>
  <div class="star"></div>
</div>

Next, apply some flexbox styling to bring it all together:

.container {
  display: flex;
  justify-content: space-between;
  align-items: center;

You have the flexibility to adjust the margin and padding of the stars, along with experimenting with justify-content.

Answer №2

Design a container that is positioned at half the width of the star icon and conceals any overflow. Then, shift the left (technically right) half of the star by half of its width along the x-axis.

The CSS Code

input[type='radio'] {
  display: none;
}

.star-container {
  cursor: pointer;
  display: inline-block;
  height: 2rem;
  width: 1rem;
  overflow: hidden;
}

.star {
  transition: color 200ms;
  height: 2rem;
  width: 2rem;
}

.star-left {
  transform: scaleX(-1) translateX(50%);
}

Star Container Code Snippet

<div className="star-container">
  <FaStarHalf
    className={i % 2 ? "star star-left" : "star"}
    color={value <= (hover || rating) ? "#ffc107" : "#e4e5e9"}
    onMouseEnter={() => setHover(value)}
    onMouseLeave={() => setHover(null)}
  />
</div>

https://i.stack.imgur.com/8vSTJ.png

https://codesandbox.io/s/half-star-rater-styled-63vso?fontsize=14&hidenavigation=1&module=%2Fsrc%2FApp.js&theme=dark

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can you explain the contrast between using require('d3') and require('d3-selection')?

While working on a nodejs application with javascript, I encountered an interesting issue. In my code, I am passing a d3 selection to a function as shown below. // mymodule.js exports.myfunc = function(ele){ if(ele instanceof d3.selection){ // do so ...

Display JSX using the material-ui Button component when it is clicked

When I click on a material-ui button, I'm attempting to render JSX. Despite logging to the console when clicking, none of the JSX is being displayed. interface TileProps { address?: string; } const renderDisplayer = (address: string) => { ...

evolving the design of mui stepper

I am looking to customize the code below for my specific needs I want to change the icon from to this: I am unable to modify the style and also need to add an intermediate step I have included , '.Mui-active': { color: '#1C6FC9', }, ...

Issues with Navigating through a Scrollable Menu

I'm having a difficult time grasping the concept and implementing a functional scrolling mechanism. Objective: Develop a large image viewer/gallery where users can navigate through images by clicking arrow keys or thumbnails in a menu. The gallery an ...

Measuring the height of a div element using Vuejs

Let me explain my current situation: I am trying to determine the height of a DIV component in order to dynamically inform its child component about its size. I have been working on implementing manual loading mode, but I have encountered an issue where t ...

Trigger a series of functions upon clicking with ReactJS

Need some assistance with an alert message functionality. I have a button labeled Checkout, and when clicked, it should clear the cart and display an alert. At present, the individual functions work as expected - calling emptyCart() works fine, and calling ...

Go back to the previous operation

Utilizing ajax to verify if a username is available by checking the MySQL database. If the username is already taken, it will return false to the form submit function. index.php $("#register-form").submit(function(){ var un = $("#un").val(); $.aj ...

Error: The function setOpenModal is not defined

I'm currently working on creating a login modal popup that will appear when a button inside a navbar is clicked. However, I'm encountering the following error: TypeError: setOpenModal is not a function Despite going through various discussions ...

Issue: The function "MyDocument.getInitialProps()" needs to return an object containing an "html" prop with a properly formatted HTML string

Check out my project on GitHub at https://github.com/Talita1996/NLW4 To start the project, I used the command yarn create next-app project_name I made changes to some files by modifying their extensions and adding new code Next, I added typescript to the ...

Issue with JavaScript Date.parse function not functioning as expected

I have implemented a date validation method in my application to check if a given date is valid or not. myApp.isValidDate = function(date) { var timestamp; timestamp = Date.parse(date); if (isNaN(timestamp) === false) { return true; } return ...

Maximizing the potential of mouse positioning in Angular

I am working with an Angular form that has a textarea <textarea class="form-control" id="message" formControlName="message" (fo ...

The $.each function seems to be stuck and not cycling through the

Dealing with a rather intricate JSON structure, I'm encountering difficulty iterating through it using the $.each() function. It seems to be related to the unusual 2-dimensional array passed in the value section of the standard array (hopefully that m ...

The spread operator in Vuex is causing compilation errors with babel, as it continuously results in a module build failure

Currently, I am utilizing a spread operator within my mapGetters object. It is crucial to use a specific babel-preset-stage for proper ES6 compilation. Even after installing babel-preset-stage-2 via npm, I encountered the following error: ERROR in ./~/bab ...

There seems to be an issue as the function reporter.beforeLaunch cannot be identified and

I am currently attempting to incorporate the protractor screenshot reporter for jasmine 2. However, I encountered the following error in the terminal: /usr/local/bin/node lib/cli.js example/conf.js /Users/sadiq/node_modules/protractor/node_modules/q/q.j ...

What are the appropriate levels of access that an operating system should provide for web-based scripting?

Contemplating the level of access web-based applications have to an operating system has been on my mind. I'm pondering: What is the most effective method for determining this currently? Are we seeing a trend towards increased or decreased access? ...

New to CSS/Ruby - What causes two adjacent buttons to have varying sizes?

The varying sizes of my search and login buttons located beside each other are puzzling me. Could it be due to the fact that the search button is enclosed within a submit_tag argument while the login button is not? If this is indeed the case, how can I mak ...

Incorporating a hamburger symbol into an established menu for easy navigation

I have come across a tutorial on creating a navigation menu with a logo positioned to the left. However, I now wish to incorporate a hamburger icon for mobile devices and I am unsure about the process. Despite my efforts to find a suitable tutorial onlin ...

How come the back button does not initiate client-side navigation in a Next.js application?

In my Next.js application utilizing GraphQL to fetch articles from a server, I encountered an issue with dynamic routing when reloading the page while on an article and attempting to navigate back. The usual scenario works as expected: Index -> [slug] ...

Issue with Vue: Calling method instantly when using :mouseover in v-for within a component

Whenever I try to incorporate :mouseover in a v-for loop within the <component>, I encounter an issue. The method assigned to the :mouseover event is triggered for each element, rather than just for the hovered elements. <Single-technology ...

Enhabling/disable choices in Material UI Autocomplete based on the option that is currently selected

I am currently working on a project that involves creating an Autocomplete component using Material UI, React Hook Form, and Yup. This particular element allows users to select multiple inputs for the days of the week. My current challenge is implementing ...