Right now I am trying to make images stack side by side, vertically and horizontally, so that there is no white spaces between them. This is what my view currently looks like.
Ideally, there would be none of that blank, white space. I have inserted the ReactJS code below with my GifViewer component that holds the . Any ideas on how I can get this to work? And the code will not run due to the axios request, so it's just for visual effect right now.
img {
display: inline !important;
width: 20%;
vertical-align: top;
height: auto;
top: 0;
left: 0;
}
<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>
class GifViewer extends Component {
render() {
return (
<img
key={this.props.keyyer}
src={`https://i.giphy.com/${this.props.id}.gif`}
/>
);
}
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
searchTerm: "",
counter: 0,
pastSearches: [],
data: null
};
this.handleChange = this.handleChange.bind(this);
}
componentDidUpdate() {
console.log("this.state.data", this.state.data);
}
componentDidMount() {
console.log("Mounted");
}
handleChange(event) {
this.setState({ searchTerm: event.target.value });
axios
.get(
`${BASE_URL}${config.apiKey}${QUERY}${this.state.searchTerm}${LIMITS}`
)
.then(result => {
this.setState({ data: result.data.data });
});
}
render() {
if (this.state.data) {
var GIFS = this.state.data.map(d => (
<GifViewer keyyer={d.embed_url} id={d.id} />
));
}
return (
<div className="container-fluid">
<div className="row py-5 bg-success">
<div className="col-8 offset-2">
<h3 className="text-center">LET'S BREAK THE INTER-WEBZ</h3>
<input
type="text"
className="form-control"
value={this.state.searchTerm}
onChange={this.handleChange}
placeholder="Search"
/>
</div>
</div>
{this.state.data ? GIFS : "Nothing yet"}
</div>
);
}
}
export default App;
My personal favorite way to resolve this is the css property object-fit: cover; (applied to your img rule).
There's a great article on the property here, but the gist (for your purpose) is that you can zoom the image to cover the whole space without stretching or distorting the image.
Related
I've just implemented the react material ui carousel, and it was pretty straightforward, the only thing i didn't catch, is how to hide buttons and show them only on over.
I noticed the props navButtonsAlwaysVisible and set it to false but it isn't enough.
Should i implement my own logic for that, or maybe I'm just missing something?
here's the component code:
import styles from '../../styles/Testimonial.module.scss'
import Image from 'next/image'
import Carousel from 'react-material-ui-carousel'
const Testimonial = _ => {
const items = [
{
imageUrl: "/png/image0.webp",
feedback: "feedback0",
name: "name0",
location: "location0"
},
{
imageUrl: "/png/image1.jpeg",
feedback: "feedback1",
name: "name1",
location: "location1"
}
]
return (
<div id="customers" className={`section ${styles.testimonial}`}>
<h2 className={`title ${styles.title}`}>Clientes Felizes</h2>
<span className={"separator"}> </span>
<Carousel
className={styles.carousel}
autoPlay={true}
stopAutoPlayOnHover={true}
interval={5000}
animation={"slide"}
swipe={true}
navButtonsAlwaysVisible={false}
navButtonsProps={{
style: {
backgroundColor: "#8f34eb",
opacity: 0.4
}
}}
>
{
items.map( (item, i) => <Item key={i} item={item} /> )
}
</Carousel>
</div>
)
}
function Item(props)
{
return (
<article className={styles.testimonial__card}>
<div className={styles.testimonial__photo_container}>
<Image
className={styles.testimonial__photo}
src={props.item.imageUrl}
alt="Testimonial"
width={312}
height={300}
/>
</div>
<p className={styles.testimonial__copy}>{props.item.feedback}</p>
<span className={styles.testimonial__name}>{props.item.name}</span>
<span className={styles.testimonial__city}>{props.item.location}</span>
</article>
)
}
export default Testimonial;
there's a prop called navButtonsAlwaysInvisible
navButtonsAlwaysInvisible={true}
You can try using Custom CSS for your purpose. Based on the current rendered markup,
.jss6 {
opacity: 0;
transition: all ease 1000ms; /* So that it does not disappear quickly */
}
You can define the hover for the parent so that it displays only when the parent container is hovered on:
.jss1.Testimonial_carousel__3rny3:hover .jss6 {
opacity: 1;
}
This is how it works now:
I have wrapper div with padding and I am dynamically adding items inside of it.
I don't want any padding on wrapper div when there is no item in it.
I have created computed method isEmpty to check if there are items or not and used it to add optional class :class={ className: isEmpty } but it doesn't work.
Here is the fiddle link: https://jsfiddle.net/2u9rtdmh/3/
You should wrap an expression for :class into ":
:class="{ className: isEmpty }"
You should read the console errors when trying to diagnose problems, i.e. your jsfiddle doesn't even have an #app element.
The correct syntax for your scenario would be :class="{ 'padding0' : isEmpty }"
Binding HTML Classes
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: "#app",
data: {
},
computed: {
isEmpty() {
return true;
}
}
})
body {
background-color: black;
}
.my-wrapper {
padding: 32px;
background-color: white;
}
.padding0 {
padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div :class="{ 'padding0' : isEmpty }" class="my-wrapper">
<div>
<div>
</div>
</div>
</div>
</div>
I have the following situtation:
2 components A and B.
A is above B in the page layout.
I wish to calculate B height css rule dynamically using it's top.
B's top is affected by A because A is rendered above it. I attached a reference to B and then apply it style by calculating the bounding rect of the ref and calculating the desired height from the top.A problem occurs when component A is taking more time to fully render than component B because A loads images that takes a bit more time to load making B's top to shift a after it was already rendered so the calculating of the height in the function needs to be called again somehow after A was fully rendered but I don't wanna make B coupled to A just because it renders before it, what can I do to solve this issue?
You can solve it using Css flexbox, check code snippet bellow.
(function () {
var loadImgBtn = document.getElementById('load-image-btn');
var loadedImg = document.getElementById('loaded-image');
loadImgBtn.addEventListener('click', function () {
loadedImg.style.display = 'block';
});
})();
.flexbox {
display: flex;
flex-direction: column;
align-items: stretch;
min-height: 350px;
}
#loaded-image {
display: none;
}
#first-block {
background: green;
}
#second-block {
background: red;
flex-grow: 1;
}
<div class="flexbox">
<div id="first-block"> Component A
<img id="loaded-image"
src="https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500">
</div>
<div id="second-block">Component B</div>
</div>
<button id="load-image-btn">Load Image</button>
If you want to calculate it programmatically you can use ref or forwardRef if you need to pass ref further down something like this
const ComponentA = React.forwardRef((props, ref) => (
<div ref={ref} className="componentA">
{props.children}
</div>
));
const ComponentB = React.forwardRef((props, ref) => (
<div ref={ref} className="componentB">
{props.children}
</div>
));
class App extends React.Component{
constructor(props){
super(props);
this.refA = React.createRef();
this.refB = React.createRef();
}
componentDidMount(){
console.log(this.refA.current.clientHeight,this.refB.current.clientHeight);
}
render(){
return (
<div className="App">
<ComponentA calculatedHeight={componentAHeight} ref={this.refA} >Component A</ComponentA>
<ComponentB calculatedHeight={componentBHeight} ref={this.refB} >Component B</ComponentB>
</div>
);
}
}
You can do it using findDOMNode too (it is depricated in strict mode). react-sizeme might be helpfull as well.
I am rendering modals in React.
My index.html looks like this:
<div id="root"></div>
<div id="modal"></div>
And all my modals are rendered (through a portal) as a child of .modal.
Each modal element has the following form:
<div class="modal-background open">
<!-- children -->
</div>
Where the class can be modal-background open or modal-background closed. The entire component is:
interface OwnProps {
children: React.ReactNode
isOpen: boolean
onExit: () => void
}
export class Modal extends React.Component<OwnProps, any> {
_exit = () => this.props.onExit();
_renderModal = () => (
<div className={`modal-background ${this.props.isOpen ? "open" : "closed"}`} onClick={this._exit}>
{this.props.children}
</div>
);
render() {
if (this.props.isOpen) {
document.body.className += " no-scroll";
} else {
document.body.classList.remove("no-scroll");
}
let elem = document.querySelector("#modal");
if (elem == null) {
console.log("Could not render modal.");
return null;
}
return ReactDOM.createPortal(this._renderModal(), elem);
}
}
And the CSS looks like:
.modal-background {
/* Other styling - this a dark backdrop for a modal child */
background-color: rgba(0,0,0,0.2);
transition: opacity 150ms ease-out;
&.closed {
opacity: 0;
pointer-events: none;
}
&.open {
pointer-events: all;
opacity: 1;
&:hover {
cursor: pointer;
}
}
}
So my modal is used like <Modal><CustomModalElement/></Modal>.
When I load the page, my modal elements briefly flash, indicating that they are not hidden on load (but a split-second afterwards).
I can fix this by adding display: none and display: inherit into the css, but then I miss the nice transitions.
Is there a better way to do this?
Not sure you need to do anything else inside your index.html file except
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<div id="modal"></div>
And for your Modal.js, you could try something along these lines:
import React from "react";
import ReactDOM from "react-dom";
const Modal = props => {
return ReactDOM.createPortal(
<div className="ui dimmer modals visible active">
<div className="ui standard modal visible active">
<div className="header">Delete Object</div>
<div className="content">
Are you sure you want to delete this?
</div>
<div className="actions">
<button className="ui primary button">Delete</button>
<button className="ui button">Cancel</button>
</div>
</div>
</div>,
document.querySelector("#modal")
);
};
export default Modal;
and then inside your other component where the user will execute the modal:
import React from "react";
import Modal from "../Modal"; // or wherever your Modal is in the file tree
const ObjectDelete = () => {
return (
<div>
ObjectDelete
<Modal />
</div>
);
};
export default ObjectDelete;
Keep in mind that the example of modal I offer here is not a reusable component.
I have an app file which contains my own custom appbar and different page components:
const styles = theme => ({
appBar: {
width:'100%',
},
});
class App extends Component {
render() {
const {classes} = this.props;
return (
<React.Fragment>
<CssBaseline />
<AppBar position="sticky" className={classes.appBar} />
<Page1 show={someCondition} />
<Page2 show={someCondition} />
.
.
<Page99 show={someCondition} />
</React.Fragment>
);
}
}
The Appbar is sticky so it always shows on the top.
Each page component has a button which is always on the top of that page:
const styles = theme => ({
button: {
width:'100%',
},
});
class Page99 extends Component {
render() {
const {classes} = this.props;
return (
<React.Fragment>
<div>
<Button variant="contained" className= {classes.button}>
Action Button
</Button>
</div>
{/* Some other stuff */>
</React.Fragment>
);
}
}
I know want this button to always be right under the appbar. So when the user scrolls down this button should remain sticky just like the appbar does. I tried to set the positioning to sticky hoping it would stack underneath it but it wouldn't. The appbar is dynamic so I don't know the exact height it will be since on different resolutions it will look different so I couldn't use something like fixed positioning.
You can set position of page container as relative and set button as absolute.
the you can align it to top right of the page or wherever you want.
Check this fiddle is this is what you need
.componentparent {
position: relative;
height:100px;
max-height: 50px;
overflow: auto;
}
.button {
position: fixed;
top: 30px;
}
.otherelements{
top: 70px;
position: relative;
}
<div id="parent-container">
<div> your app bar </div>
<div class='componentparent'>
<button class='button'>my button</button>
<div class='otherelements'>your component</div>
</div>
</div>
Place your button inside your appbar and set your button to position to absolute and add top: 100% to move it exactly at the bottom of appbar.