Positioning a button on top of another item in css styled components - css

i am trying to get a button to overlap and be positioned at a certain place of a searchbar. Here is what it currently looks like. I tried using the transform: translateX() property but when I add a :hover element, the button gets moved back to its original position before the transform: translateX() event
But this is what i want it to look like.
Here is my css code. I'm using styled components.
const Button = styled.button`
display:block;
width:40px;
height:40px;
/* line-height:80px; */
border: none;
border-radius: 50%;
color:#f5f5f5;
text-align:center;
text-decoration:none;
background: #0072FF;
box-shadow: 0 0 3px gray;
font-size:20px;
font-weight:bold;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
transform: translateX(-180%);
&:hover {
outline: none;
transform: scale(1.05);
}
`;
const Input = styled.input`
color: inherit;
border : none;
background: none;
padding-left: 10px;
width: 100%;
&:focus {
outline : none;
}
`;
const Form = styled.form`
background-color : white;
border-radius : 7px;
height: 5%;
width: 75%;
align-items: center;
display: flex;
transition: all .3s;
margin-left: 6%;
`;
const Img = styled.img`
height: 15px;
width: 15px;
margin-left: 10px;
`
And here are my components.
import React from 'react'
import NewChat from '../newChat/newChat';
import { Input, Form, Img } from './searchBar.elements';
function SearchBar() {
return (
<Form>
<Img src={require("../../../../assets/img/search.svg")} />
<Input placeholder="Find people and conversations" />
<NewChat />
</Form>
)
}
export default SearchBar;
import React from 'react'
import { Button} from './newChat.elements';
import plus from '../../../../assets/img/plus_button.svg';
function NewChat() {
return (
<div>
{/* <img src={require("../../../../assets/img/plus_button.svg")} /> */}
<Button>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 4C11.4477 4 11 4.44772 11 5V11H5C4.44772 11 4 11.4477 4 12C4 12.5523 4.44772 13 5 13H11V19C11 19.5523 11.4477 20 12 20C12.5523 20 13 19.5523 13 19V13H19C19.5523 13 20 12.5523 20 12C20 11.4477 19.5523 11 19 11H13V5C13 4.44772 12.5523 4 12 4Z"
fill="currentColor"
/>
</svg>
</Button>
</div>
)
}
export default NewChat;

First for the i am trying to get a button to overlap and be positioned at a certain place of a searchbar maybe you should use position: relative on your father component (Form) and position: absolute on your Button, with that your father becomes a parameter for the absolute position of the button so you can use the properties Left, Top, Right, Bottom to get it to the correct location.
const Form = styled.form`
...otherProperties,
position: relative;
`;
const Button = styled.button`
...otherProperties,
position: absolute,
right: 180px // for example
top: 50px // example
`;
Second for the when I add a :hover element, the button gets moved back to its original position before the transform: translateX() event I think it is because you change the TRANSFORM property inside Button.
const Button = styled.button`
display:block;
width:40px;
height:40px;
/* line-height:80px; */
border: none;
border-radius: 50%;
color:#f5f5f5;
text-align:center;
text-decoration:none;
background: #0072FF;
box-shadow: 0 0 3px gray;
font-size:20px;
font-weight:bold;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
transform: translateX(-180%); // Here the transform property is translateX //
&:hover {
outline: none;
transform: scale(1.05); // Here the transform property translateX now becomes scale //
`;
To correct this you need to make the hover property not lose the previous one.
&:hover {
outline: none;
transform: translateX(-180%) scale(1.05);
}

Related

How to ensure that a div is always centered when another one disappears after an animation?

(CSB for reference)
I have a button comprised of an icon and some text. When the button is hovered, the text moves to the right, and so does the icon. It creates a nice animation
The problem is I make this transition happen with the following code:
.button:not(.disabled):hover .icon {
transform: translate3d(150%, 0, 0);
}
The 150% is just an arbitrary value, if you go inside App.js and change the width of the icon (line 10), you can tell that it's no longer centered. I can't wrap my head around a solution that would ensure the following (my goals):
When the button is not hovered, both the icon and the text should be center.
When the button is hovered, only the icon should be ultimately centered.
Would appreciate any guidance.
First give your button a fixed width.
.button {
width: 130px;
}
and then you just need to set the position of your icon class to absolute on button hover.
.button:not(.disabled):hover .icon {
position: absolute;
}
Perfectly-smooth solution that works for every situation:
body {
display: grid;
place-items: center;
gap: 1em;
}
button {
--gap: 5px;
font-size: 14px;
padding: .3em .7em;
background: none;
border: 2px solid black;
border-radius: 4px;
cursor: pointer;
overflow: hidden;
}
button > div {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
white-space: nowrap;
gap: var(--gap);
transition: .3s ease-out;
}
button > div > i {
flex: 0;
transition: inherit;
}
button > div > span {
flex: 1;
transition: inherit;
}
button:hover > div {
width: calc(200% + var(--gap));
}
button:hover > div > i {
flex: 1;
color: crimson;
}
button:hover > div > span {
opacity: 0;
}
<button>
<div>
<i>♥️</i>
<span>Short</span>
</div>
</button>
<button>
<div>
<i>♥️</i>
<span>Normal label</span>
</div>
</button>
<button>
<div>
<i>♥️</i>
<span>Very long label text example</span>
</div>
</button>
Codepen demo

Link/Chain CSS Transitions

I know this should be a no-brainer, but for some reason I really just cannot figure out how to link my CSS transitions... I am attaching a website with widgets that act how I want mine to act: https://kion.io/resources
I love that when you hover on the widget, all CSS transitions happen at the same time over that one div/a href
I am attempting to do the same, and I have written all of my code but I have to hover individually over my elements... this is for a site that is not yet done, but I will post a link to the page that I am referring to. Specifically focusing on the widgets in the middle of the page. They scale up, BUT I want the arrows to move to the right when you hover over the entire div like in Kion's site. I can only figure out how to make them move when you hover over them specifically.
My site: https://cloudshape.net/cloudshape/
My code:
/*WIDGETS*/
.card a {
text-decoration: none;
color: black;
}
.card a:hover {
color: black;
}
.card {
font-family: 'helvetica', sans-serif;
margin: 25px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
background-image: url('https://cloudshape.net/wp-
content/uploads/2022/02/clear-bg.png');
background-repeat: no-repeat;
background-position: center;
background-size: cover;
transition: background-image 2s ease-in-out;
}
.white-square {
width: 310px;
height: 330px;
background-color: white;
border: 2px solid black;
border-radius: 6px;
box-shadow: 0 0 10px 2px #202020;
padding: 15px;
text-align: center;
transition: transform .4s ease-in-out, border .4s ease-in-out;
}
/*WIDGET ARROW BUTTONS*/
.btn img {
width: 80px;
margin-top: -20px;
margin-left: 120px;
}
.btn img:hover {
margin-left: 130px;
}
.btn img {
transition: margin-left .7s ease;
}
<div class="card">
<a href="">
<div class="white-square">
<span class="icon"><img alt="security" src="https://cloudshape.net/wp-content/uploads/2022/02/shielddot-color.png"/></span>
<h5>Dev(Sec)Ops/SRE<br>Architecture & Modernization</h5>
<p>Short for development, security and operations — automates the integration of security at every phase of the software development lifecycle.</p>
<span class="btn"><img alt="button" src="https://cloudshape.net/wp-content/uploads/2022/02/arrow.png"/></span>
</div>
</a>
</div>
You could use this CSS rule to target your arrow when your white square is hovered :
.white-square:hover .btn img {
margin-left: 130px;
}

:Active works in styled components but :checked doesn't

I am attempting to transition from css to styled components. I am creating a toggle switch component. The animation on the :active class works when the switch is checked but, when the checkbox is checked the switch does not move to the left like it would with just normal css.
import React from 'react';
import styled from 'styled-components'
const Button = styled.span`
content: '';
position: absolute;
top: 3.7px;
left: 5px;
width: 42px;
height: 42px;
border-radius: 45px;
transition: 0.2s;
background: #fff;
box-shadow: 0 0 2px 0 rgba(10, 10, 10, 0.29);
`;
const Label = styled.label`
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
width: 100px;
height: 50px;
background: dodgerblue;
border-radius: 100px;
position: relative;
transition: background-color 0.2s;
&:active ${Button} {
width: 50px;
}
`;
const Input = styled.input`
height: 0;
width: 0;
visibility: hidden;
&:checked ${Button} {
left: calc(100% - 5px);
transform: translateX(-100%);
}
`;
const Switch = ({ isOn, handleToggle, onColor }) => {
return (
<>
<Input
checked={isOn}
onChange={handleToggle}
className='react-switch-checkbox'
id={`react-switch-new`}
type='checkbox'
/>
<Label
style={{ background: isOn && onColor }}
className='react-switch-label'
htmlFor={`react-switch-new`}>
<Button className={`react-switch-button`} />
</Label>
</>
);
};
export default Switch;
Your problem is not related to styled components. The rule &:checked ${Button} { assumes the Button is a child of Input, but it's actually a child of Input's sibling Label.
Update the styled component rule to:
&:checked + ${Label} ${Button} {
left: calc(100% - 5px);
transform: translateX(-100%);
}
Sandbox

React: Caret icon keeps moving outside of dropdown menu whenever page is resized to iPad or smaller

I have a styled react component that features a hand rolled dropdown menu including a caret icon and every time I test the responsiveness of the dropdown the caret icon pops outside. I've wrapped the dropdown inside of a larger component to place everything on the same line and then included the icon inside of the styled select component. I've used this methodology in another app and the dropdown is completely responsive and doesn't have any issues with icon placement so I'm completely scratching my head with this one. Any help/suggestions would be great
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { FaCaretDown } from 'react-icons/fa'
import Table from '../core/Table'
import SubHeader from '../elements/SubHeader'
import EligibleOffer from './EligibleOffer'
import { tableDataProps, tableColumnProps } from '../../propTypes'
const BUNDLE_KEY = 'bundle'
const rowKey = 'id'
class OfferBundlesTable extends Component {
static propTypes = {
bundles: PropTypes.arrayOf(tableDataProps),
columns: tableColumnProps,
viewedOfferIds: PropTypes.arrayOf(PropTypes.string),
onBundleSelect: PropTypes.func
}
static defaultProps = {
viewedOfferIds: []
}
renderCell = (cell = {}) => (
<div>
{cell.title && <SubHeader>{cell.title}</SubHeader>}
<p>{cell.details}</p>
</div>
)
renderBundle = bundle => (
<StyledOffer
offer={bundle}
onOfferSelect={this.props.onBundleSelect}
viewed={this.props.viewedOfferIds.includes(bundle.OfferId)}
/>
)
getColumns = columns =>
Object.entries(columns).reduce(
(cols, [key, value]) => ({
...cols,
[key]: {
...value,
renderCell: key === BUNDLE_KEY ? this.renderBundle : this.renderCell
}
}),
{}
)
render() {
const { bundles = [], columns = [] } = this.props
return (
<div>
<DropdownRow>
<StyledSelect>
<StyledStrong>SORT BY: </StyledStrong>
<select>
<option>Default</option>
<option>Promo Price (High to Low)</option>
<option>Promo Price (Low to High)</option>
<option>Alphabetically (A-Z)</option>
<option>Alphabetically (Z-A)</option>
<option>Internet Tier (High to Low)</option>
<option>Internet Tier (Low to High)</option>
</select>
<StyledSelectIcon size="1.5rem" />
</StyledSelect>
<StyledSelect>
<StyledStrong>CONTRACT TERMS (MONTHS):</StyledStrong>
<select>
<option>36</option>
<option>24</option>
<option>12</option>
</select>
<StyledSelectIcon size="1.5rem" />
</StyledSelect>
</DropdownRow>
<StyledTable
rowKey={rowKey}
rows={bundles}
columns={this.getColumns(columns)}
/>
</div>
)
}
}
const StyledTable = styled(Table)`
th:first-child {
width: 25%;
}
`
const StyledOffer = styled(EligibleOffer)`
margin-bottom: 15px;
`
const DropdownRow = styled.div`
th:first-child {
width: 25%;
}
flex: 1;
display: flex;
align-items: stretch;
padding: 20px 30px 20px 10px;
width: 60%;
margin-left: 42%;
`
const StyledSelectIcon = styled(FaCaretDown)`
position: absolute;
top: 0;
right: 10px;
bottom: 0;
margin: auto;
color: black;
pointer-events: none;
`
const StyledSelect = styled.div`
position: relative;
margin-left: auto;
select {
padding: 5px 45px 5px 10px;
font-size: 1.2rem;
line-height: 1.4rem;
font-weight: 500;
color: black;
border: 2px solid black;
height: 36px;
appearance: none;
background: transparent;
border-radius: 0;
}
`
const StyledStrong = styled.strong`
padding-right: 5px;
`
export default OfferBundlesTable
After looking at your code, I would suggest an alternative approach, including the caret in the css for your select. This makes it impossible for it to move away from the select, as it's now part of it. Run the snippet below to see it work--of course you would want to put that stuff into the styled-component css definition, and remove the <StyledSelectIcon/> altogether (here's a forked stackblitz).
Styled component definition:
const StyledSelect = styled.div`
position: relative;
margin-left: auto;
select {
padding: 5px 45px 5px 10px;
font-size: 1.2rem;
line-height: 1.4rem;
font-weight: 500;
color: black;
border: 2px solid black;
height: 36px;
background-color: transparent;
border-radius: 0;
-moz-appearance: none;
-webkit-appearance:none;
appearance: none;
background-image: url('data:image/svg+xml;utf8,<svg fill="black" viewBox="0 0 320 512" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"></path></svg>');
background-repeat: no-repeat;
background-position: right 8px center;
}
`
Snippet to run here:
.customselect{
padding: 5px 45px 5px 10px;
font-size: 1.2rem;
line-height: 1.4rem;
font-weight: 500;
color: black;
border: 2px solid black;
height: 36px;
background-color: transparent;
border-radius: 0;
-moz-appearance: none;
-webkit-appearance:none;
appearance: none;
background-image: url('data:image/svg+xml;utf8,<svg fill="black" viewBox="0 0 320 512" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg"><path d="M31.3 192h257.3c17.8 0 26.7 21.5 14.1 34.1L174.1 354.8c-7.8 7.8-20.5 7.8-28.3 0L17.2 226.1C4.6 213.5 13.5 192 31.3 192z"></path></svg>');
background-repeat: no-repeat;
background-position: right 8px center;
}
<select class="customselect">
<option>Option A</option>
<option>Option B</option>
<option>Option C</option>
<option>Option D</option>
</select>

react-facebook-login button style

I am using facebook login at my login page, my website is fully responsive, but my facebook login button is not responsive. (i.e when i am using small screen size, facebook login button should change it's with)
Please refer images below:
1) Normal case:
2) When Screen is resized to pixels less than 399 (screen width < 400)
3) How i want it to be (in resized browser on PC, or on mobile)
My react code is:
<div style={{display: 'flex',flexWrap: 'wrap' }} >
<FacebookLogin
appId={facebookAppId}
autoLoad={false}
fields="name,email,picture"
callback={this.props.SocialSignUp}
cssClass="btnFacebook"
icon={<i className="fa fa-facebook" style{{marginLeft:'5px'}}>
</i>}
textButton = " Sign In with Facebook"
/>
<GoogleLogin
clientId={googleClientId}
onSuccess={this.props.SocialSignUp}
onFailure={this.props.SocialSignUp}
className="btnGoogle"
>
<i className="fa fa-google-plus" style={{ marginLeft:
'5px' }}/>
<span> Sign In with Google</span>
</GoogleLogin>
</div>
My CSS is
.btnFacebook {
width: 165px;
height:35px;
border-radius: 4px;
background: #3b5998;
color:white;
border:0px transparent;
text-align: center;
margin:5px;
display: inline-block;
}
.btnGoogle {
margin:5px;
width: 165px;
height:35px;
border-radius: 4px;
background: #db3236;
color:white;
border:0px transparent;
text-align: center;
}
.btnFacebook:hover {
background: #3b5998;
opacity: 0.6;
}
.btnGoogle:hover {
background: #db3236;
opacity: 0.6;
}
#media only screen and (max-width : 399px) {
.btnFacebook,.btnGoogle{
width: 100%
}
}
Please note that I am using react-facebook-login package for rendering facebook button and react-google-login package for rendering google button.
Help Please!!!
Here is a simplified example using styled-components
It's using your css and resizing the way it should.
You can copy/paste this Component and import it into your app maybe it helps figuring out your problem.
import React, { Component } from 'react'
import styled from 'styled-components';
const Wrapper = styled.div`
#media only screen and (max-width : 399px) {
width: 10%
}
`
const BtnFacebook = styled.button`
width: 165px;
height:35px;
border-radius: 4px;
background: #3b5998;
color:white;
border:0px transparent;
text-align: center;
margin:5px;
display: inline-block;
&:hover{
background: #3b5998;
opacity: 0.6;
}
`;
const BtnGoogle = styled.button`
margin:5px;
width: 165px;
height:35px;
border-radius: 4px;
background: #db3236;
color:white;
border:0px transparent;
text-align: center;
&:hover{
background: #3b5998;
opacity: 0.6;
}
`
class Login extends Component {
render() {
return (
<div style={{ display: 'flex', flexWrap: 'wrap' }} >
<Wrapper>
<BtnFacebook >
Sign In with Facebook
</BtnFacebook >
<BtnGoogle>
Sign In with Google
</BtnGoogle >
</Wrapper>
</div>
)
}
}
export default Login
It seems working for me. Just did a work around on your code. Tell the exact error. It would be helpful. Here I attached the output.

Resources