Gaya CSS sebaris dalam Bereaksi: bagaimana cara menerapkan: hover?

178

Saya sangat menyukai pola CSS inline di Bereaksi dan memutuskan untuk menggunakannya.

Namun, Anda tidak dapat menggunakan :hoverpemilih dan sejenisnya. Jadi apa cara terbaik untuk mengimplementasikan highlight-on-hover saat menggunakan gaya CSS sebaris?

Satu saran dari #reactjs adalah memiliki Clickablekomponen dan menggunakannya seperti ini:

<Clickable>
    <Link />
</Clickable>

The Clickablememiliki hoverednegara dan dibagikan sebagai alat peraga untuk Link tersebut. Namun, Clickable(cara saya mengimplementasikannya) membungkus Linkdalam divsehingga dapat diatur onMouseEnterdan onMouseLeaveuntuk itu. Ini membuat hal-hal sedikit rumit (misalnya spandibungkus divberperilaku berbeda dari span).

Apakah ada cara yang lebih sederhana?

fhucho
sumber
1
Anda benar - satu-satunya cara untuk mensimulasikan: melayang-layang selektor dll dengan gaya inline adalah dengan menggunakan onMouseEnterdan onMouseLeave. Mengenai implementasi yang tepat dari itu - sepenuhnya terserah Anda. Untuk melihat contoh spesifik Anda, mengapa tidak membuat <Clickable/>bungkusnya span?
Chris Houghton
3
saya akan menyarankan menggunakan style sheet eksternal bersama dengan plugin ExtractText Webpack, ini akan membantu Anda dalam menjalankan lagi jika Anda ingin ServerRender jika tidak Anda dapat mencoba Radium github.com/FormidableLabs/radium
abhirathore2006
Saat ini Styled Component adalah solusi terbaik untuk mensimulasikan semua kemungkinan css / scss dalam bereaksi.
Ahmad Behzadi

Jawaban:

43

Saya dalam situasi yang sama. Benar-benar menyukai pola menjaga styling di komponen tetapi keadaan hover sepertinya merupakan rintangan terakhir.

Apa yang saya lakukan adalah menulis mixin yang dapat Anda tambahkan ke komponen Anda yang membutuhkan status hover. Mixin ini akan menambah hoveredproperti baru ke status komponen Anda. Ini akan diatur ke truejika pengguna melayang di atas simpul DOM utama dari komponen dan mengatur kembali falsejika pengguna meninggalkan elemen.

Sekarang dalam fungsi render komponen Anda, Anda dapat melakukan sesuatu seperti:

<button style={m(
     this.styles.container,
     this.state.hovered && this.styles.hover,
)}>{this.props.children}</button>

Sekarang setiap kali hoveredstatus perubahan komponen akan rerender.

Saya juga membuat repo kotak pasir untuk ini yang saya gunakan untuk menguji beberapa pola ini sendiri. Periksa jika Anda ingin melihat contoh implementasi saya.

https://github.com/Sitebase/cssinjs/tree/feature-interaction-mixin

Wim Mostmans
sumber
3
bukan solusi yang baik untuk lari lebih lama, Radium akan menjadi pilihan yang lebih baik atau menggunakan stylesheet eksternal
abhirathore2006
16
@ abhirathore2006 Radium bekerja dengan cara yang sama dan pertanyaannya adalah secara khusus bagaimana melakukan ini tanpa menggunakan stylesheet eksternal
Charlie Martin
Bukankah lebih masuk akal jika menggunakan operator vanilla spread?
PAT-O-MATION
102

Saya pikir onMouseEnter dan onMouseLeave adalah cara untuk pergi, tapi saya tidak melihat perlunya komponen pembungkus tambahan. Inilah cara saya mengimplementasikannya:

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={linkStyle} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
}

Anda kemudian dapat menggunakan status hover (benar / salah) untuk mengubah gaya tautan.

Jonathan
sumber
1
Ini sepertinya menutupi :hovertetapi tidak:focus
Adam Tuttle
3
@AdamTuttle react memiliki onFocusacara; sehingga Anda dapat melakukan hal yang sama :focusseperti :hover, kecuali alih-alih membutuhkan onMouseEnterdan onMouseLeaveAnda hanya perluonFocus
Jonathan
7
Sadarilah bahwa metode ini memaksa eksekusi pada utas utama sedangkan acara CSS yang khas ditangani jauh lebih efisien.
Hampus Ahlgren
54

Terlambat ke pesta tetapi datang dengan solusi. Anda dapat menggunakan "&" untuk menentukan gaya untuk mengarahkan anak ke lain-lain dll:

day: {
    display: "flex",
    flex: "1",
    justifyContent: "center",
    alignItems: "center",
    width: "50px",
    height: "50px",
    transition: "all 0.2s",
    borderLeft: "solid 1px #cccccc",

    "&:hover": {
      background: "#efefef"
    },
    "&:last-child": {
      borderRight: "solid 1px #cccccc"
    }
},
Hitesh Sahu
sumber
1
Ini bukan solusi, pertanyaannya adalah bagaimana melakukannya dengan INLINE css, bukan dengan style sheet terpisah.
Emmy
36
Bung, lihat lebih dekat. Ini gaya inline.
Jarosław Wlazło
15
Ini tidak berfungsi dengan Bereaksi. Anda memerlukan perpustakaan tambahan seperti komponen yang ditata.
GG.
3
Itu tidak bekerja dengan gaya inline, contoh ini membawa kebingungan. Jika benar-benar berfungsi, berikan contoh yang lebih baik dengan komponen lengkap.
Alexandre
2
Luar biasa! Bekerja seperti pesona!
Fyodor
26

Anda dapat menggunakan Radium - ini adalah alat sumber terbuka untuk gaya sebaris dengan ReactJS. Ia menambahkan persis pemilih yang Anda butuhkan. Sangat populer, coba lihat - Radium on npm

Gyro
sumber
Saya baru saja menemukan posting ini, bagaimana Anda menerapkan Radium dalam situasi berikut? module.exports = React.createClass({ displayName: 'App',})
1
@Rkhayat Anda dapat membungkusnya sebagai module.exports = Radium(React.createClass({ displayName: 'App',}))atau menugaskan kelas pada nilai dan menambahkan @Radiumdekorator di atasnya sebagai dokumen menyebutkan github.com/FormidableLabs/radium#usage
pbojinov
ada juga hal hebat yang disebut CSS;)
Pixelomo
11

Dukungan penuh CSS adalah alasan utama jumlah besar perpustakaan CSSinJS ini, untuk melakukan ini secara efisien, Anda perlu menghasilkan CSS yang sebenarnya, bukan gaya inline. Gaya inline juga jauh lebih lambat dalam bereaksi dalam sistem yang lebih besar. Penafian - Saya memelihara JSS .

Oleg Isonen
sumber
9

Made Style It - sebagian - karena alasan ini (yang lain tidak setuju dengan implementasi lib / sintaks lain dan inline stylings kurangnya dukungan untuk awalan nilai properti). Percayalah kita harus bisa hanya menulis CSS dalam JavaScript dan memiliki komponen yang sepenuhnya lengkap HTML-CSS-JS. Dengan string template ES5 / ES6 kita sekarang dapat dan itu bisa sangat cantik! :)

npm install style-it --save

Sintaks Fungsional ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return Style.it(`
      .intro:hover {
        color: red;
      }
    `,
      <p className="intro">CSS-in-JS made simple -- just Style It.</p>
    );
  }
}

export default Intro;

Sintaks JSX ( JSFIDDLE )

import React from 'react';
import Style from 'style-it';

class Intro extends React.Component {
  render() {
    return (
      <Style>
      {`
        .intro:hover {
          color: red;
        }
      `}

        <p className="intro">CSS-in-JS made simple -- just Style It.</p>
      </Style>
    );
  }
}

export default Intro;
Joshua Robinson
sumber
Saya perhatikan pada contoh Sintaks JSX, tautan JSFiddle memiliki kode yang benar, tetapi contoh yang ditunjukkan di sini tidak memiliki tanda kurung penutup setelah tag Gaya penutup dan lekukan tidak aktif mungkin karena tanda kurung yang hilang.
bradleygsmith
8

Menambahkan ke jawaban Jonathan , berikut adalah acara untuk membahas fokus dan status aktif, dan penggunaan onMouseOveralih-alih onMouseEnterkarena yang terakhir tidak akan menggelembung jika Anda memiliki elemen anak dalam target acara yang sedang diterapkan.

var Link = React.createClass({

  getInitialState: function(){
    return {hover: false, active: false, focus: false}
  },

  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },

  toggleActive: function(){
    this.setState({active: !this.state.active})
  },

  toggleFocus: function(){
    this.setState({focus: !this.state.focus})
  },

  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else if (this.state.active) {
      linkStyle = {backgroundColor: 'blue'}
    } else if (this.state.focus) {
      linkStyle = {backgroundColor: 'purple'}
    } 

    return(
      <div>
        <a style={linkStyle} 
          onMouseOver={this.toggleHover} 
          onMouseOut={this.toggleHover} 
          onMouseUp={this.toggleActive} 
          onMouseDown={this.toggleActive} 
          onFocus={this.toggleFocus}> 
          Link 
        </a>
      </div>
    )
  }
Rachel Cantor
sumber
7

Inilah solusi saya menggunakan React Hooks. Ini menggabungkan operator spread dan operator ternary.

style.js

export default {
  normal:{
    background: 'purple',
    color: '#ffffff'
  },
  hover: {
    background: 'red'
  }
}

Button.js

import React, {useState} from 'react';
import style from './style.js'

function Button(){

  const [hover, setHover] = useState(false);

  return(
    <button
      onMouseEnter={()=>{
        setHover(true);
      }}
      onMouseLeave={()=>{
        setHover(false);
      }}
      style={{
        ...style.normal,
        ...(hover ? style.hover : null)
      }}>

        MyButtonText

    </button>
  )
}
PAT-O-MATION
sumber
6

Berkenaan dengan komponen yang ditata dan react-router v4 Anda dapat melakukan ini:

import {NavLink} from 'react-router-dom'

const Link = styled(NavLink)`     
  background: blue;

  &:hover {
    color: white;
  }
`

...
<Clickable><Link to="/somewhere">somewhere</Link></Clickable>
Isaac Pak
sumber
6

Ini bisa menjadi peretasan yang bagus karena memiliki gaya inline di dalam komponen reaksi (dan juga menggunakan: hover fungsi CSS):

...

<style>
  {`.galleryThumbnail.selected:hover{outline:2px solid #00c6af}`}
</style>

...
tomericco
sumber
5

Checkout Typestyle jika Anda menggunakan Bereaksi dengan Teks.

Di bawah ini adalah contoh kode untuk: hover

import {style} from "typestyle";

/** convert a style object to a CSS class name */
const niceColors = style({
  transition: 'color .2s',
  color: 'blue',
  $nest: {
    '&:hover': {
      color: 'red'
    }
  }
});

<h1 className={niceColors}>Hello world</h1>
paibamboo
sumber
4

Anda dapat menggunakan modul css sebagai alternatif, dan juga bereaksi-css-modul untuk pemetaan nama kelas.

Dengan begitu Anda dapat mengimpor gaya Anda sebagai berikut dan menggunakan css normal yang dicakup secara lokal ke komponen Anda:

import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);

Berikut adalah contoh modul css webpack

svnm
sumber
FYI: Jika Anda menggunakan Meteor, periksa paket ini: github.com/nathantreid/meteor-css-modules . Saya menggunakannya sendiri sejauh ini telah sukses besar.
Spiralis
Ini adalah cara yang bagus untuk komponen reaksi gaya, tetapi tidak cukup memberi Anda semua kontrol gaya inline. Misalnya, Anda tidak dapat mengubah :hovergaya saat runtime seperti dengan Radium atau onMouseOversolusi berbasis lainnya
Charlie Martin
4

onMouseOver dan onMouseLeave dengan setState pada awalnya sepertinya sedikit berlebihan bagi saya - tetapi karena ini adalah bagaimana reaksinya bekerja, sepertinya solusi termudah dan terbersih bagi saya.

rendering theming css serverside misalnya, juga merupakan solusi yang baik dan menjaga komponen reaksi lebih bersih.

jika Anda tidak perlu menambahkan gaya dinamis ke elemen (misalnya untuk tema), Anda tidak boleh menggunakan gaya inline sama sekali, tetapi gunakan kelas css.

ini adalah aturan html / css tradisional untuk menjaga html / JSX tetap bersih dan sederhana.

lukas gurschler
sumber
4

Cara sederhana menggunakan operator ternary

var Link = React.createClass({
  getInitialState: function(){
    return {hover: false}
  },
  toggleHover: function(){
    this.setState({hover: !this.state.hover})
  },
  render: function() {
    var linkStyle;
    if (this.state.hover) {
      linkStyle = {backgroundColor: 'red'}
    } else {
      linkStyle = {backgroundColor: 'blue'}
    }
    return(
      <div>
        <a style={this.state.hover ? {"backgroundColor": 'red'}: {"backgroundColor": 'blue'}} onMouseEnter={this.toggleHover} onMouseLeave={this.toggleHover}>Link</a>
      </div>
    )
  }
Hemadri Dasari
sumber
1

Dengan menggunakan kait:

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

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

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

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

  return { fadeStyle, onMouseEnter, onMouseLeave };
};

const ListItem = ({ style }) => {
  const { fadeStyle, ...fadeProps } = useFade();

  return (
    <Paper
      style={{...fadeStyle, ...style}}
      {...fadeProps}
    >
      {...}
    </Paper>
  );
};
Jaroslav
sumber
0

Saya menggunakan solusi hack-ish yang cukup untuk ini di salah satu aplikasi terbaru saya yang berfungsi untuk tujuan saya, dan saya menemukan ini lebih cepat daripada menulis fungsi pengaturan hover kustom di vanilla js (meskipun, saya tahu, mungkin bukan praktik terbaik di sebagian besar lingkungan ..) Jadi, jika Anda masih tertarik, ini dia.

Saya membuat elemen induk hanya untuk menahan gaya javascript inline, lalu seorang anak dengan className atau id yang stylesheet css saya akan latch ke dan menulis gaya hover di file css khusus saya. Ini berfungsi karena elemen anak yang lebih granular menerima gaya js inline melalui pewarisan, tetapi memiliki gaya hover ditimpa oleh file css.

Jadi pada dasarnya, file css saya yang sebenarnya ada hanya untuk tujuan menahan efek hover, tidak ada yang lain. Ini membuatnya cukup ringkas dan mudah dikelola, dan memungkinkan saya melakukan pekerjaan berat dalam gaya komponen Bereaksi in-line saya.

Ini sebuah contoh:

const styles = {
  container: {
    height: '3em',
    backgroundColor: 'white',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    borderBottom: '1px solid gainsboro',
  },
  parent: {
    display: 'flex',
    flex: 1,
    flexDirection: 'row',
    alignItems: 'stretch',
    justifyContent: 'flex-start',
    color: 'darkgrey',
  },
  child: {
    width: '6em',
    textAlign: 'center',
    verticalAlign: 'middle',
    lineHeight: '3em',
  },
};

var NavBar = (props) => {
  const menuOptions = ['home', 'blog', 'projects', 'about'];

  return (
    <div style={styles.container}>
      <div style={styles.parent}>
        {menuOptions.map((page) => <div className={'navBarOption'} style={styles.child} key={page}>{page}</div> )}
      </div>
    </div>
  );
};


ReactDOM.render(
  <NavBar/>,
  document.getElementById('app')
);
.navBarOption:hover {
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="app"></div>

Perhatikan bahwa gaya inline "child" tidak memiliki set properti "warna". Jika ya, ini tidak akan berhasil karena gaya inline akan diutamakan di atas stylesheet saya.

witygass
sumber
0

Saya tidak 100% yakin apakah ini jawabannya, tetapi ini trik yang saya gunakan untuk mensimulasikan CSS: efek hover dengan warna dan gambar sejajar.

`This works best with an image`

class TestHover extends React.PureComponent {
render() {
const landingImage = {     
"backgroundImage": "url(https://i.dailymail.co.uk/i/pix/2015/09/01/18/2BE1E88B00000578-3218613-image-m-5_1441127035222.jpg)",
"BackgroundColor": "Red", `this can be any color`
"minHeight": "100%",
"backgroundAttachment": "fixed",
"backgroundPosition": "center",
"backgroundRepeat": "no-repeat",
"backgroundSize": "cover", 
"opacity": "0.8", `the hove trick is here in the opcaity slightly see through gives the effect when the background color changes`
    }

  return (
    <aside className="menu">
        <div className="menu-item">
          <div style={landingImage}>SOME TEXT</div>
        </div>
    </aside>
      ); 
  }
}
ReactDOM.render(
    <TestHover />,
  document.getElementById("root")
);

CSS:

.menu {
top: 2.70em;
bottom: 0px;
width: 100%;
position: absolute;
}

.menu-item {
cursor: pointer;
height: 100%;
font-size: 2em;
line-height: 1.3em;
color: #000;
font-family: "Poppins";
font-style: italic;
font-weight: 800;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
}

Sebelum melayang

.menu-item:nth-child(1) {
color: white;
background-color: #001b37;
} 

Saat melayang

.menu-item:nth-child(1):hover {
color: green;
background-color: white;
}

Contoh: https://codepen.io/roryfn/pen/dxyYqj?editors=0011

Rory
sumber
0
<Hoverable hoverStyle={styles.linkHover}>
  <a href="https://example.com" style={styles.link}>
    Go
  </a>
</Hoverable>

Di mana Hoverable didefinisikan sebagai:

function Hoverable(props) {
  const [hover, setHover] = useState(false);

  const child = Children.only(props.children);

  const onHoverChange = useCallback(
    e => {
      const name = e.type === "mouseenter" ? "onMouseEnter" : "onMouseLeave";
      setHover(!hover);
      if (child.props[name]) {
        child.props[name](e);
      }
    },
    [setHover, hover, child]
  );

  return React.cloneElement(child, {
    onMouseEnter: onHoverChange,
    onMouseLeave: onHoverChange,
    style: Object.assign({}, child.props.style, hover ? props.hoverStyle : {})
  });
}
Sig
sumber