Implementing intricate inline styles in React for interactive features like hover and active states on components like buttons

I'm currently styling my buttons using the following CSS with Bootstrap.

.btn-primary {
    background-color: #229ac8;
    background-image: linear-gradient(to bottom, #23a1d1, #1f90bb);
    background-repeat: repeat-x;
    border-color: #1f90bb #1f90bb #145e7a;
    color: #ffffff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}
.btn-primary:hover, .btn-primary:active, .btn-primary.active, .btn-primary.disabled, .btn-primary[disabled] {
    background-color: #1f90bb;
    background-position: 0 -15px;
}

In React, I have created a button component like this:

const MyButton = ({children, onClick, classNames, ...rest }) =>
(
    <button
        onClick   = {onClick}
        className = {`${classNames}`}
        {...rest}
    >
        {children}
    </button>
);

Now, I need to change the button's color dynamically based on server data.

Question 1:

How can I apply inline styles to completely change the button's appearance?

Question 2:

Is it possible to utilize SCSS features like mixins in React to generate button styles based on a variable like color?

Question 3:

Should I opt for inline styles or use CSS-in-JS with classnames?

When creating a reusable component like a button, is it better to use a global class that can be reused across different instances or define local inline styles for each instance?

Answer №1

Using CSS in JS for React with Pseudo Classes and MQ Support

When it comes to writing CSS for React, there are numerous libraries available that support pseudo classes. However, most of them require you to either inline your CSS or write it directly in your JavaScript code, which is something I highly recommend.

Exploring CSS Modules for a Better CSS Organization

Another option to consider is using CSS modules, which allows you to write your CSS in a more traditional way while still benefiting from the advantages of modularization. Setting up CSS modules with Webpack is fairly straightforward, and you can then import your CSS as an object and use it in your components.

import styles from './Button.css'

const MyButton = ({children, onClick, type='primary', ...rest }) =>
(
    <button
        onClick   = {onClick}
        className = {styles.primary}
        {...rest}
    >
        {children}
    </button>
);

Enhancing Component Decoupling

It's also a good practice not to pass classes directly to your components and instead handle conditions within the component itself. By using a library like `classnames`, you can easily manage dynamic class names based on props.

import classnames from 'classnames'

const MyButton = ({children, onClick, type='primary', ...rest }) =>
(
    <button
        onClick   = {onClick}
        className = {classnames('.btn', { [`btn-${type}`]: true })}
        {...rest}
    >
        {children}
    </button>
);

By combining CSS Modules with the `classnames` library, you can create powerful and flexible styling solutions for your React components.

Answer №2

Personally, I prefer utilizing global CSS and connecting it to Webpack when working with React. This approach helps maintain a cleaner and more modular codebase, allowing for easier editing.

As far as I am aware, SCSS features cannot be directly applied inline within React components.

If you find yourself needing to apply inline styles in React, you can do so by following this example;

var buttonStyle = {
    backgroundColor: "#229ac8",
    backgroundImage: "linear-gradient(to bottom, #23a1d1, #1f90bb)",
    backgroundRepeat: "repeat-x",
    borderColor: "#1f90bb #1f90bb #145e7a",
    color: "#ffffff",
    textShadow: "0 -1px 0 rgba(0, 0, 0, 0.25)"
}
<button style={buttonStyle}>Button</button>

Answer №3

hover: when using hooks for fading effect:

const useFading = () => {
  const [ fade, setFade ] = useState(false);

  const onMouseEnter = () => {
    setFade(true);
  };

  const onMouseLeave = () => {
    setFade(false);
  };

  const fadeEffect = !fade ? {
    opacity: 1, transition: 'all .2s ease-in-out',
  } : {
    opacity: .5, transition: 'all .2s ease-in-out',
  };

  return { fadeEffect, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeEffect, ...fadeProperties } = useFading();

  return (
    <Paper
      style={{...fadeEffect, ...style}}
      {...fadeProperties}
    >
      {...}
    </Paper>
  );
};

This technique can be applied to handle more intricate scenarios as well.

Answer №4

Issue 1:

How do I apply inline styling for a button's complete style?

According to the official documentation:

In React, inline styles are specified using an object with camel-cased style properties and their corresponding values, rather than as a string.

For the following CSS code:

.btn-primary {
    background-color: #229ac8;
    background-image: linear-gradient(to bottom, #23a1d1, #1f90bb);
    background-repeat: repeat-x;
    border-color: #1f90bb #1f90bb #145e7a;
    color: #ffffff;
    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
}

An inline representation of it would be

const MyButton = () =>
(
    <button
        className = { {
            backgroundColor: '#229ac8',
            backgroundImage: 'linear-gradient(to bottom, #23a1d1, #1f90bb)',
            backgroundRepeat: 'repeat-x',
            borderColor: '#1f90bb #1f90bb #145e7a',
            color: '#ffffff',
            textShadow: '0 -1px 0 rgba(0, 0, 0, 0.25)'
        } }
    </button>
);

Issue 2

Can I incorporate SCSS features like mixins in React to dynamically generate button styles by passing color as a variable?

React's inline styling is essentially a representation of CSS without additional features. However, since inline styles are object-oriented, you can dynamically generate them to simulate SCSS mixins and utilize variables.

A SCSS mixin such as the following

@mixin border-radius($radius) {
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    -ms-border-radius: $radius;
    border-radius: $radius;
}

Can be achieved with a function like this

const borderRadius = ($radius) => {
    return {
        WebkitBorderRadius: $radius;
        MozBorderRadius: $radius;
        MsBorderRadius: $radius;
        borderRadius: $radius;
    }
}

const MyComponent = () => {
    var inlineStyle = Object.assign({}, borderRadius(10), {
        backgroundColor: 'white'
    })

    return (
        <div style={ inlineStyle }>
            Hello, world!
        </div>
    )
}

Issue 3

Would it be better to use inline styles or classnames with CSS in JS?

This question does not have a definitive answer. However, it's recommended to use classnames for general purposes and inline styles for specific cases. Ultimately, the choice depends on how you want to organize and structure your code.

Answer №5

To dynamically change the color of a button, you can define a JavaScript object with inline styles. Here's an example:

const normalButtonStyle = {
  background:'gray',
  color:'black',
  borderColor:'white'
}
const buttonCompleteStyle = {
  background:'red',
  color:'white',
  borderColor:'black'
} // You can also import these styles from another file

const MyButton = ({children, status, onClick, classNames, ...rest }) =>
(
  <button
    onClick   = {onClick}
    className = {`${classNames}`}
    {...rest}
    style={status === 'complete' ? buttonCompleteStyle : normalButtonStyle}
  >
    {children}
  </button>
);

While not tested, this is a general idea. You can explore how Material UI implements this feature.

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

AngularJS: Triggering events in one controller to update data in another controller

I've tried several examples, but I'm not getting the expected results. In my project, I have two controllers - one for a dropdown and one for a table. When a user selects an item from the dropdown, a factory triggers a get request to update the t ...

How to capture a specific part of a model using Autodesk Forge Viewer

I have a situation where I have 20 element Ids that I need to capture screenshots of in a specific size (400x400) like a detail view. The current viewer I am using has different dimensions, so I'm wondering if there is a way to achieve this and return ...

Personalize JSON Reporter to Display Captured Information - WebdriverIO

I'm currently in the process of scraping data from an android app using WDIO and APPIUM. After successfully storing the scraped data in an array, I now aim to automatically output this array data to a .json file, rather than manually copying and pasti ...

Implementing a props interface for conditions in styled components within a React application using Typescript

This specific component is created using React along with the "styled components" library to manage user input. In the case of invalid user input, the corresponding styles should be displayed as shown below (class invalid). Although this example functions ...

The CSRF token in Laravel Blade seems to be unreachable by Vue

Having a blade with the following code snippet. <meta name="csrf-token" content="{{ csrf_token() }}"> <covid-form> </covid-form> Inside the covid-form component, there is a form structure like this: <form @submit.prevent="send"&g ...

Can Hapi-Joi validate a payload consisting of either an Array of objects or a plain Javascript object?

How can I create a schema to validate payloads for a post call that accepts either a single JS object or an array of objects to be saved in the database? JS object { label: 'label', key: 'key', help_text: 'text' } ...

Cannot assign type void to 'Intrinsic Attributes & Dispatch<SetStateAction<>>'

Just starting out with typescript and ran into this error: Error :Type '{ setTasks: void; }' is not assignable to type 'IntrinsicAttributes & Dispatch<SetStateAction<IStudy[]>>'. Property 'setTasks' does not e ...

Transforming an Ext.data.TreeStore data structure into a JSON format

How can I convert an Ext.data.TreeStore to a string for saving to Local Storage? I tried using Ext.encode() but it's giving me a circular structure error. Has anyone encountered this issue and found a workaround? ...

Tips for aligning an image on top of another image

Here is the code I am working with (also pasted below). My goal is to create a layout with two columns, where the first column features two images and the second column displays some text. In the first column, I specifically want the first image to have a ...

Using percentages to position Div elements

Currently, I am working on an HTML page that requires a div element spanning the full width of the page. My goal is to arrange other divs within this full-width div using percentages rather than pixels. The class associated with this div is .question. Thi ...

Ways to conceal specific content within a text using CSS

Help me with the updated code <html> <title>css</title> <head> <style> #st { z-index: -114; margin-right: -80px; } </style> </head> State Code : <span><span id="st"></span>Maharashtra - MH ...

What is the best way to ensure that one method waits for another method to complete before proceeding?

Below is a React method that needs completion for uploading images to cloudinary and setting the URL in state before executing the API call addStudent. The order of execution seems correct at first glance, but the last API call crashes due to base64 data n ...

React-vertical-timeline component is failing to display on the webpage. The content in the output HTML remains concealed due to the presence of the "is-hidden"

I am facing an issue while trying to incorporate a vertical timeline into my project. The generated HTML code does not display the timeline as expected. Upon inspection, I noticed that the classes are set to be hidden with "is-hidden". It seems like there ...

A Node.js function may not provide a response immediately due to a pending request

Here is a simple upload method using node.js and express.js: upload: function(req, res, next){ // Loop through each uploaded file async.each(req.files.upload, function(file, cb) { async.auto({ // Create new path and unique file ...

Stuck with the Same Theme in the AppBar of material-UI?

Currently, I am attempting to modify the theme of a material-UI AppBar by utilizing states. Strangely enough, although the icons are changing, the theme itself is not. If you'd like to take a look at the code, you can find it here: https://codesandbo ...

Styling CSS: Create circular images with dynamic text positioning or resizing on screens larger than 768px

I'm struggling to figure out how to create a circular profile picture on a background image that remains responsive and maintains its position across different screen sizes. Currently, I've been using fixed margin values to adjust the position, ...

unable to locate the nested routes in the folder for remix

Hey there, I've been using the remix to create a basic page and I'm trying to organize the routes using folders. Here is my project directory: - app/ - root.tsx - examples/ - route.tsx - child1/ - account.tsx In the examples di ...

The incorrect sequence of Angular/Protractor functions is causing issues within the tests

Trying to extract the values from a column in a grid and compare them before and after sorting can be tricky. I have two functions set up for this task - one to retrieve the initial column values, and another to check the order post-sorting. However, there ...

Troubleshooting issue with alignment in Material UI using Typescript

<Grid item xs={12} align="center"> is causing an issue for me No overload matches this call. Overload 1 of 2, '(props: { component: ElementType<any>; } & Partial<Record<Breakpoint, boolean | GridSize>> & { ...

Avoid replacing CSS properties, instead use jQuery to supplement them

Can anyone help me figure out how to use the jquery .css() function without overwriting existing values, but instead adding additional values to css properties? For example, I have an element that currently has the css transform:translate(-50%, -50%). I w ...