CSS only works sometimes on dynamic image rendering in React - css

I am building a recommender system for clothing and for that I am currently implementing a front-end with React. This front end is a chat in which the user can send text messages or upload an image. I dynamically render the messages from the bot (back-end) and the user (front-end). My problem is that the image behaves in an unpredictable way and first gets positioned correctly under the last message but every new messages just "ignores" the image and gets displayed wrong.
This is (part of) the react rendering output:
<div className="body">
{/* Go through the array and display every message either as user or as bot message */}
{messages.map((message, index) => {
if (message[2] === "bot") {
if (message[3] === "image") {
return (
<img
src={message[0]}
key={index}
className="image botImage"
alt="imageDisplayError"
></img>
);
}
return (
<p className="message botMessage" key={index}>
{message[0]}
</p>
);
} else {
if (message[3] === "image") {
return (
<img
src={message[0]}
key={index}
className="image usrImage"
alt="imageDisplayError"
></img>
);
} else {
return (
<p className="message usrMessage" key={index}>
{message[0]}
</p>
);
}
}
})}
</div>
This is the relevant CSS code:
.message {
padding: 10px;
width: fit-content;
border-radius: 10px;
margin-bottom: 15px;
/* Breaks messages into multiple lines */
max-width: 350px;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
}
.botMessage {
background-color: #037d7a;
color: white;
}
.usrMessage {
margin-left: auto;
background-color: #07a7a4;
}
.image {
/* padding-top: 15px; */
max-width: 350px;
max-height: 250px;
/* margin-bottom: 15px; */
}
.usrImage {
float: right;
}
This is the output (I have the inspector open so you can see the bounding boxes)
As you can see the image renders correctly under the initial message but every new messages just ignores the bounding box.
I would be grateful for ideas on how to fix this :)
I have already tried different CSS tricks with paddings and margins and so on as well as enclosing every element in a wrapper div so that an image and a text message get handled the same way.

The solution was posted by Nirav.
This CSS seems to do the trick:
.message {
margin: 0;
padding: 10px 18px;
width: fit-content;
border-radius: 5px;
max-width: 350px;
overflow-wrap: break-word;
word-wrap: break-word;
hyphens: auto;
margin-bottom: 5px;
}
.botMessage {
background-color: #037d7a;
color: white;
}
.image {
display: flex;
max-width: 350px;
max-height: 250px;
aspect-ratio: 16/9;
object-fit: cover;
object-position: top;
border-radius: 5px;
margin-bottom: 5px;
}
.usrMessage {
margin-left: auto;
background-color: #07a7a4;
color: white;
}
.usrImage {
margin-left: auto;
}

Related

Angular Material Virtual Scroller gets stuck sometimes on Mobile only unsure why

HTML
<section fxLayout="column" fxLayoutAlign="center center" class="vwubble-section" fxFlex="auto">
<ng-container *ngIf="(allBubbles$ | async)">
<cdk-virtual-scroll-viewport #scroller itemSize="355" class="scrolling-container scrollbar-hidden" minBufferPx="1200" maxBufferPx="1200">
<vw-vwubbles-item *cdkVirtualFor="let bubble of allBubbles$"
[bubble]="bubble">
</vw-vwubbles-item>
</cdk-virtual-scroll-viewport>
</ng-container>
</section>
CSS
.vwubble-section {
padding: 0px;
margin: 0px;
padding-top: 20px;
min-width: 100%;
/* padding-top: 300px; */
background-color: #000;
/* margin-bottom: 60px; */
/* height: 1400px;
overflow:hidden; */
}
.mat-form-field-appearance-fill .mat-form-field-flex{
background-color: white;
}
::ng-deep .mat-select-value {
color: #673ab7;
}
.scrolling-container{
/* display: flex; */
min-height: 1600px;
/* flex-grow: 1; */
width: 100%;
max-width:800px;
overflow-y: scroll;
padding: 0px;
overflow-x: hidden;
}
.scrolling-container::-webkit-scrollbar {
width: 0; /* Remove scrollbar space */
background: transparent; /* Optional: just make scrollbar invisible */
}
So these vwubble-items are like tweets, and the scroll gets stuck when the user tries to scroll down on mobile, but the weird thing is that I am using this same scrolling method for the replies to these main threads, and these replies never get stuck ever.
Any help would be much appreciated.

Centering a div with css in nextjs (moves but doesn't completely center)

I have tried looking at many questions on StackOverflow and none of them have helped me. I think that I have a more specific problem, there might be some type of CSS attribute that is stopping the div from centering. Maybe I need to use flexbox to solve this?
here is the JSX:
import { useState } from 'react'
import styles from '../styles/login.module.css'
import Head from 'next/head'
export default function Login() {
const [loginDetails, setLoginDetails] = useState({username: "", password: ""});
function handleUsernameChange(e) {
var value = e.target.value;
setLoginDetails({username: value, password: loginDetails.password});
}
function handlePasswordChange(e) {
var value = e.target.value;
setLoginDetails({username: loginDetails.username, password: value});
}
function SubmitLogin() {
console.log(loginDetails);
}
return (
<>
<Head>
<title>Login</title>
</Head>
<div className={styles.container}>
<h1 className={styles.subheading}>Login</h1>
<label>Username:</label>
<input type="text" placeholder="username" className={styles.input} onChange={handleUsernameChange} />
<label>Password:</label>
<input type="password" placeholder="password" className={styles.input} onChange={handlePasswordChange} />
<button className={styles.button} onClick={SubmitLogin}>Login</button>
</div>
</>
);
}
Here is the CSS:
.heading {
font-size: 3rem;
}
.subheading {
font-size: 2rem;
}
.pheading {
font-size: 1.5rem;
}
.paragraph {
margin-left: 1rem;
}
.container {
display: flex;
flex-direction: column;
gap: 10px;
margin: 0 auto;
width: 25%;
}
.input {
border-radius: 5px;
max-width: 200px;
height: 30px;
border: 1px solid #d7dbd9;
}
.input:focus {
outline: none;
border: 1px solid #67f0ab;
}
.button {
border: 2px solid #67f0ab;
border-radius: 5px;
color: #67f0ab;
background: none;
max-width: 100px;
height: 30px;
}
.button:hover {
background-color: #67f0ab;
color: #FFF;
}
.button:active {
background-color: #49de93;
}
The element I am trying to center is the div wrapping the login form. It has the class of .container, this class is what I was editing in my CSS to try and solve the problem. I can get the element to move to different spots, but I can't center it.
Ok so I figured out what the problem was, it was that the max-width of my container was larger than that of my widest element inside of the container, in this case it happened to be the inputs
I changed the max-width value of my container to 200px which is the same as my .input class, and the container and all of its elements were then centered.

allowing dropdown to overflow outside of div and extend as far as it needs

I am using the react-multi-carousel library in conjuction with the react select library like this:
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
<Carousel
swipeable={false}
draggable={false}
showDots={true}
responsive={responsive}
ssr={true} // means to render carousel on server-side.
infinite={true}
autoPlaySpeed={1000}
keyBoardControl={true}
customTransition="all .5"
transitionDuration={500}
containerClass="carousel-container"
removeArrowOnDeviceType={["tablet", "mobile"]}
dotListClass="custom-dot-list-style"
itemClass="carousel-item-padding-40-px"
centerMode={true}
renderDotsOutside={true}
>
{dmtfs.map((fl) => <div>{(ivrDests.length !== 0) && <StoryCarouselItem key={fl.value} dest_id={fl.value} ivr_dests={ivrDests} options={props.options} />}</div>)}
</Carousel>
StoryCarouselItem rendering:
return (
<div className="StoryCarouselItem">
<div className="StoryCarouselItemCounter">
<div className="StoryCarouselItemCounterText">
{dtmf}
</div>
</div>
<div className="StoryCarouselItemName">
{name}
</div>
<div className="StoryDropdown">
<Select styles={customStyles}
options={props.options}
placeholder={IVRSound}
value={selectedIVROption}
onChange={updateIVR}
/>
</div>
</div>
The code above works fine and looks good before dropping down as you can see below:
Carousel
However, when I click the dropdown, it does not overflow outside of the div and spill into other sections to reveal the whole dropdown like I want it to. Instead, it gets caught within the dropdown and only shows a little bit.
Example:
Carousel 2
Any idea how I can change the styling to accommodate this change?
Here's the relevant styling I have right now:
.StorySelection{
color: #392F5A;
font-family: 'Poppins';
font-weight: 700;
font-size: 20px;
margin-top: 5%;
}
.StoryCarousel{
margin-top: 5%;
padding-bottom: 10%;
padding-left: 5%;
padding-right: 5%;
}
.StoryCarouselBorder{
background: #fff;
border-style: solid;
border-color: #ABABAB;
border-width: 10px;
padding-top: 2.3%;
padding-bottom: 1.3%;
}
.StoryCarouselItem{
height: 20%;
width: 75%;
margin-top: 5%;
background: #392F5A;
}
.StoryCarouselItemCounter {
margin-top: 10%;
height: 60px;
width: 60px;
background-color: #EEC8E0;
border-radius: 50%;
display: inline-block;
}
.StoryCarouselItemCounterText{
color: #fff;
font-size: 24px;
text-align: center;
margin-top: 20%;
}
.StoryCarouselItemName {
color: #fff;
margin-top: 8%;
}
.StoryDropdown{
padding-bottom: 10%;
z-index: 20;
overflow: visible;
}
.react-multi-carousel-dot-list {
position: static !important;
margin-top: 1% !important;
margin-bottom: 0 !important;
}
Use the menuPortalTaget prop to portal the menu. This will allow it to overflow outside of the div. Other than that you may require a custom MenuList component to adjust the listing styling.

Image Height is distorted

I'm creating a resume website. I'm adding content to the Job.js component, and I'm encountering an issue with logo. The height seems to expand when the desc exceeds the height of the component. If the desc is short, I do not have this issue. I'm also not having this problem when flex-direction is column.
I tried adjusting padding-bottom of .job-container img, but while the image returned to normal, there was unwanted padding at the bottom.
Relevant Code
Job.js
import React from 'react';
import '../css/Job.css';
function Job(props) {
console.log(props.name);
const jobList = props.job.map(j =>
<div className='job-container'>
<img src={j.logo} alt={j.alt} />
<div className='description'>
<div>
<a href={j.link} rel='noopener noreferrer' target='_blank'>
{j.companyName}
</a>
</div>
<div>{j.title}</div>
<div>{j.duration}</div>
<div>{j.location}</div>
<div>{j.desc.map(paragraph => <p>{paragraph}</p>)}</div>
</div>
</div>
)
return (
<div>{jobList}</div>
);
}
export default Job;
Job.css
:root {
--image-spacing: 30px;
}
.job-container {
border: 2px solid red;
padding: 0px 5%;
display: flex;
flex-direction: row;
}
.job-container img {
border: 2px solid red;
border-radius: 3px;
display: block;
height: auto;
width: 35%;
}
.job-container .description {
line-height: 1.45;
padding-left: var(--image-spacing); /* Change this. */
}
.job-container a {
color: black;
text-decoration: none;
}
/* Responsive Mode */
#media only screen and (max-width: 768px) {
.job-container {
/* Line up description and image. */
flex-direction: column;
}
.job-container img {
border-radius: 3px;
margin: auto;
width: 75%;
}
.job-container .description {
padding-left: 0px;
padding-top: var(--image-spacing);
}
}
.content {
display: block;
}
I solved this problem by adding align-self: start; to .job-container img.

Long heading text results in empty gap

Currently my movie heading code looks like this:
.moview-info h1 {
color: #fff;
margin: 0 0 15px 0;
font-weight: normal;}
And I tried adding these lines:
display:block;
word-wrap: break-word;
max-width: 700px;
It fixes the issue partly, because when I'm shrinking my browser window, the star rating causes the heading go up and not overlap. Is there any way to fix this issue besides not displaying star rating?
Rating star code:
position: absolute;
left: 50%;
margin-left: -70px;
font-size: 130px;
width: 140px;
height: 140px;
line-height: 140px;
short title long title
This styling is usually done with { display: flex; justify-content: space-between; } as the CSS of the parent element of the title and the star. Demo below (the JS is just to animate the text):
const titleElt = document.querySelector('#title');
let titleValue = '';
setInterval(() => {
if (titleValue.length>70) {
titleValue = '';
} else {
titleValue += Math.floor(10*Math.random());
}
titleElt.innerHTML = titleValue;
}, 100);
body {
margin: 0;
font-size: 2em;
}
header {
display: flex;
justify-content: space-between;
width: 100%;
}
#title {
width: 90%;
word-wrap: break-word;
}
#star {
width: 10%;
}
<header>
<div id="title"></div>
<div id="star">⭐</div>
</header>

Resources