CSS, display blocks to different sizes - javascript

I got main block, for example it it 400px,
in this block i could have a lot of block, and i have 3 situations
i need to display score on 1 line.
1) When i got 100% - it shold be in the corner of green block
2) When it got a small size, Percentages should have "margin-left: 15px " to text, dont know, how to explain
3) And when it is for example 50% it should be after the bar
And the main problem, all text sholud be in this background, after this i will add onClick function that will close and open Teams(this you will see in the demo), so this block with all background will be receizing onClick, so all DIVs in this block with background
https://codepen.io/anon/pen/pWXaej
class Application extends React.Component {
percentsToPx ( score ) {
return score *4
}
render() {
const examples = [
{
name: 'Example 1',
score: 100,
teams: [ { name: 'Example 1' }, { name: 'Example 1' }, { name: 'Example 1' } ]
},
{
name: 'Example 2',
score: 55,
teams: [ { name: 'Example 2' }, { name: 'Example 2' }, { name: 'Example 2' } ]
},
{
name: 'Example 1',
score: 4,
teams: [ { name: 'Example 3' }, { name: 'Example 3' }, { name: 'Example 3' } ]
}
]
return <div className='project'>
{examples.map( ( it, index) => {
const size = this.percentsToPx( it.score)
return (
<div className='projectTab'>
<div style={{ display: 'inline-block' }}>
<div style={{ width: size, background: 'green', display: 'inline-block' }} className='projectBlock'>
<div className='projectText'>
<h1 className='projectTextMain'>{it.name}</h1>
<div>
{it.teams.map( ( team, index ) => {
return (
<div style={{ marginLeft: 20 }} key={index}>
<h2 style={{
color: 'black',
whiteSpace: 'nowrap',
cursor: 'default'
}}>{team.name}</h2>
</div>
);
} )}
</div>
</div>
</div>
<div style={{ width: it.score, display: 'inline-block' }}></div>
</div>
<h2 className='projectTextPercents'>{it.score}%</h2>
</div>)
})}
</div>;
}
}
/*
* Render the above component into the div#app
*/
React.render(<Application />, document.getElementById('app'));
What I want to do
What I have
and styles
.projects {
display: flex;
width: 400px;
flex-direction: column;
align-items: stretch;
margin-top: 10px;
&-tab {
border-top: 1px solid grey;
&:hover {
background: white;
}
&:last-child {
border-bottom: 1px solid grey;
}
}
&-block {
display: flex;
align-items: baseline;
}
&-text {
display: inline-block;
minHeight: 100%;
height: 100%;
margin-left: -10px;
&-main {
color: black;
white-space: nowrap;
display: inline-block;
cursor: default;
margin-left: 30px;
}
&-percents {
display: inline-block;
color: grey;
margin-left: 10px;
vertical-align: top;
cursor: default;
}
}
}
THANKS FOR YOUR HELP

I would suggest the following approach: as I see, you generate elements' width and put it right in the markup. So, you could generate also an attribute (lets say data-w) for an element with value based on the element's width. Then you could target those elements via css. In such a case you need to generate on the server-side some small styles as well for the cases when width is not equal to 100%:
div {
padding: 10px;
border: 1px solid green;
min-height: 38px;
color: white;
background-color: orange;
margin: 10px 0px;
position: relative;
box-sizing: border-box;
}
div[data-w="full"]:after {
position: absolute;
top: calc(50% - 8px);
white-space: nowrap;
right: 5%;
content: '100%';
}
/* -- Generate the corresponding styles on the server-side and put them right in the markup for every item with width not equal to 100% -- */
div[data-w="average1"]:after {
position: absolute;
top: calc(50% - 8px);
white-space: nowrap;
color: black;
right: -45px;
content: '50%';
}
div[data-w="average2"]:after {
position: absolute;
top: calc(50% - 8px);
white-space: nowrap;
color: black;
right: -45px;
content: '47%';
}
div[data-w="small"]:after {
position: absolute;
top: calc(50% - 8px);
white-space: nowrap;
color: black;
right: -115px;
content: 'example 3 16%';
}
/* -- End of note -- */
<div data-w="full" style="width: 300px">example 1</div>
<div data-w="average1" style="width: 150px">example 2.1</div>
<div data-w="average2" style="width: 140px">example 2.2</div>
<div data-w="small" style="width: 50px"></div>

Related

The way to optimize react and Typescript codes

In this case, I used React + TypeScript and ant-design. The following code works perfectly but I want the codes to be summarized as much as possible. This is about starting a site that has 3 pages. For example, how can I write this part (const { id, title, description, background } = splash;) so that I don't need to define (splashs[index].background , splashs[index].title, splashs[index].description) all the time.
Thank you in advance for your cooperation.
.splash {
height: 100vh;
position: relative;
overflow: hidden;
}
.bg {
background-color: var(--cjp);
}
.BgGradiant {
background: linear-gradient(107.78deg, rgba(80, 21, 100, 0) 1.87%, rgba(80, 21, 100, 0.05) 18.6%, rgba(80, 21, 100, 0.51) 25.79%, #1C3396 99.02%, #1C3396 51.08%);
}
.context{
width: 80%;
}
.content {
text-align: center;
}
.content h1,
.content p {
color: var(--cwh);
}
.backgroundImage>img {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: -1;
-o-object-fit: cover;
object-fit: cover;
}
.logo {
width: 100%;
text-align: center;
}
.btns {
display: flex !important;
align-items: center;
justify-content: space-between;
-webkit-margin-start: auto;
margin-inline-start: auto;
-webkit-margin-end: auto;
margin-inline-end: auto;
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btns :global(.ant-btn){
background-color: var(--cwh);
border-radius: var(--borderRadius12);
position: relative;
padding: 4px 10px !important;
}
.btns :global(.ant-btn)::after{
content: "";
position: absolute;
width: 125%;
height: 125%;
top: 50%;
left: 50%;
border: 1px solid var(--chb);
border-radius: var(--borderRadius14);
transform: translate(-50%, -50%);
}
.btns :global(.ant-btn > span){
margin-left: 0 !important;
}
.btns :global(.ant-btn > span > svg){
fill: var(--cal);
}
.btnSkip {
background-color: unset;
outline: none;
border: none;
color: var(--cca);
}
.btnLogin{
-webkit-margin-before: 2rem;
margin-block-start: 7rem;
}
.btnLogin :global(.ant-btn){
border-radius: var(--borderRadius10);
background-color: var(--cwh);
color: var(--cjp);
}
.btnLogin :global(.ant-btn > span){
font-family: "Display-Bold";
}
.dots {
position: absolute;
bottom: 17%;
display: flex !important;
align-items: center;
justify-content: center;
left: 50%;
transform: translateX(-50%);
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.dotActive {
background-color: var(--cwh);
}
.dotDeActive {
background-color: var(--cca);
}
.dot:not(:last-child) {
-webkit-margin-end: 0.5rem;
margin-inline-end: 0.5rem;
}
.contentInner{
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
-webkit-padding-before: 2rem;
padding-block-start: 2rem;
-webkit-padding-after: 3rem;
padding-block-end: 3rem;
}
.contentInner1{
justify-content: space-between;
}
.contentInner2{
justify-content: flex-end;
}
import React, { useState } from 'react';
import { useNavigate } from "react-router-dom";
import { Row, Col, Button } from 'antd';
import { ArrowRightOutlined } from '#ant-design/icons';
import Container from '../../Components/UI/Container/Container'
import classes from './Splash.module.css';
import { backgroundSplash1, backgroundSplash2, logoImage } from '../../Assets/index';
const Splash = () => {
let navigate = useNavigate();
const [index, setIndex] = useState<number>(0);
const {
splash,
bg,
BgGradiant,
context,
content,
backgroundImage,
logo,
btns,
btnLogin,
btnSkip,
dots,
dot,
dotActive,
dotDeActive,
contentInner,
contentInner1,
contentInner2,
} = classes
const splashs = [
{
id: 0,
title: 'Page 1 : title 1',
desctiption: '1- Lorem ipsum 1 ',
background: logoImage,
},
{
id: 1,
title: 'Page 2 : title 2',
desctiption: '2- Lorem ipsum 2 ',
background: backgroundSplash1,
},
{
id: 2,
title: 'Page 3 : title3',
desctiption: '3- Lorem ipsum 3',
background: backgroundSplash2,
}
];
const nextBnt = () => {
setIndex(index + 1);
if (index === splashs.length - 1) {
return navigate("/login");
}
}
const skipBtn = () => {
console.log('skip ');
return navigate("/login");
}
const loginBtn = () => {
return navigate("/login");
}
return (
<>
<Row>
<Col xs={24}>
<section
className={`${index === 0 ? bg : BgGradiant} ${splash}`}>
{
splashs.map((splash) => {
const { id, title, desctiption, background } = splash;
console.log(title, "title");
return (
<>
{
index !== 0 && (
<div className={backgroundImage}>
<img src={splashs[index].background} />
</div>
)
}
<Container key={id} className={backgroundImage}>
<div className={`${index === 0 ? contentInner1 : contentInner2} ${contentInner}`}>
{
index === 0 && (
<div className={logo}>
<img src={logoImage} alt="logoImage" />
</div>
)
}
<div className={context}>
<div className={content}>
<h1>{splashs[index].title}</h1>
<p>{splashs[index].desctiption}</p>
</div>
{/* BTNS */}
{
index === splashs.length - 1 ? (
<div className={btnLogin}>
<Button block onClick={loginBtn}>Login</Button>
</div>
) : (
<div className={btns}>
<button className={btnSkip} onClick={skipBtn}>skip</button>
<Button onClick={nextBnt}> <ArrowRightOutlined /></Button>
</div>
)
}
</div>
</div>
</Container>
</>
)
})
}
<div className={dots}>
{
Array.from({ length: 3 }).map((item, idx) => {
return (
<div key={idx} className={`${dot} ${index === idx ? dotActive : dotDeActive}`}></div>
)
})
}
</div>
</section>
</Col>
</Row>
</>
)
}
export default Splash;
Just an advice, your question isn't really well formulated so it's hard to understand what are you trying to accomplish. Try to keep the questions clear and remove any redundant code so the community can better understand it.
If I'm assuming correctly that you don't want to use splash[index] then you should change splash[index].title to title, same for the other props.
Since you already destructured the splash object with const { id, title, description, background } = splash; all these will be available.
Another thing here is, .map method returns the item in the array so I don't see the point in you using the index inside the loop to access the item from the array.

How we can have the real color on an picture thumbnail when we click on it?

For my project here I tried to have a color picture when I clicked on one of the four different pictures.
The four different picture are thumbnails, and when I click on a thumbnail, this one is active and I want to have this active thumbnail with the right logo color, like the Photoshop profile here. And the other Thumbnails and in grey, because we didn't click on it so they are considered inactive.
So I tried to do this with filter property and I didn't find the right solution.
So can you help me please to find the right solution?
I can show you my code of my project :
Vue.component('carousel', {
template: `
<div class="card-carousel" >
<div class="thumbnails">
<div
v-for="(image, index) in images"
:key="image.id"
:class="['thumbnail-image', (activeImage == index) ? 'active' : '']"
#click="activateImage(index)">
<img :src="image.thumb" class="active"/>
</div>
</div>
<div class="containe-carousel">
<span id = "textespan"> {{currentImage.text}}</span>
<div class="photoshop-screenshot">
<img :src="currentImage.big" alt="">
</div>
<div class="card-img">
<img :src="currentImage2.big2" alt="">
</div>
</div>
</div>
`,
computed: {
currentImage() {
return this.images[this.activeImage];
},
currentImage2() {
return this.images[this.activeImage];
}
},
data() {
return {
activeImage: 0,
}
},
methods: {
activateImage(imageIndex) {
this.activeImage = imageIndex;
},
},
props: ['images']
});
.section{
background-color: black;
}
.card-carousel {
user-select: none;
position: relative;
}
.containe-carousel {
padding-top: 5%;
}
.thumbnails {
display: flex;
justify-content: space-evenly;
flex-direction: row;
}
.thumbnail-image {
display: fixed;
align-items: center;
cursor: pointer;
padding: 2px;
}
.thumbnail-image > img {
width: 100%;
height: auto;
transition: all 250ms;
filter: grayscale(100%);
}
.thumbnail-image:selected> img {
box-shadow: 2px 2px 6px 1px rgba(0,0,0, 0.5);
visibility: hidden;
filter: none;
}
.card-img {
position: relative;
}
.card-img > img {
margin: 0 auto;
padding-top: 7%;
z-index: 2;
}
.photoshop-screenshot {
position:absolute;
z-index: 1;
width: 65%;
left:50%;top:75%;
}
.active{
filter: contrast(1000%)
/* black to white */
invert(100%)
/* white to off-white */
sepia(100%)
/* off-white to yellow */
saturate(10000%)
/* do whatever you want with yellow */
hue-rotate(90deg);
}
#textespan {
text-align: center;
font-size: 300%;
}
.containe-carousel span {
color: white;
font-weight: bold;
}
<section class="section" id="app">
<div class="container">
<div class="text-center" style="margin:0px 50px">
<div class="heading-underscore">
<h2 class="dk-5q-color">
<?php say("X50Q-dashboard-title"); ?>
</h2>
</div>
</div>
<div class="columns">
<div class="column ">
<div class="card-content">
<carousel
:starting-image="0"
:show-progress-bar="true"
:images="images"
></carousel>
</div>
</div>
</div>
</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<script src ="/x/x50q-rgb-mechanical-keyboard/x50q-cloud-js.js"></script>
<script>
var app = new Vue({
el: '#app',
data() {
return {
images: [
{
text : 'Photoshop',
id: '1',
big: '/images/das-keyboard-x50q/photoshop-profile.PNG',
big2: '/images/das-keyboard-x50q/photoshop-screenshot.png',
thumb: '/images/das-keyboard-x50q/photoshop-logo.jpg'
},
{
text : 'Aurocad',
id: '2',
big: '/images/das-keyboard-x50q/autocad-profile.png',
big2: '/images/das-keyboard-x50q/autocad-screenshot.png',
thumb: '/images/das-keyboard-x50q/autocad-logo.png'
},
{
text : ' Counter-Strike',
id: '3',
big: '/images/das-keyboard-x50q/counterstrike-profile.png',
big2: '/images/das-keyboard-x50q/counterstrike-screenshot.jpg',
thumb: '/images/das-keyboard-x50q/counterstrike-logo.png'
},
{
text : 'League of Legends',
id: '4',
big: '/images/das-keyboard-x50q/leagueoflegends-profile.png',
big2: '/images/das-keyboard-x50q/leagueoflegends-screenshot.png',
thumb: '/images/das-keyboard-x50q/leagueoflegends-logo.jpg'
}
],
}
}
});
</script>
Problem 1: .active filter does not remove grayscale
When the image is clicked, you apply an .active class, which applies an exaggerated filter (making it look like a photo negative) instead of removing the grayscale:
.active {
filter: contrast(1000%)
/* black to white */
invert(100%)
/* white to off-white */
sepia(100%)
/* off-white to yellow */
saturate(10000%)
/* do whatever you want with yellow */
hue-rotate(90deg);
}
The CSS should be either:
filter: grayscale(0);
OR to remove all filters:
filter: none;
Problem 2: All thumbnails are .active
While the .active class is dynamically added to .thumbnail-image, it's also statically applied to all thumbnails (the img child element). This will make all images appear in the "active" state all the time. The static class should be removed:
<!-- <img :src="image.thumb" class="active"/> --> <!-- DON'T DO THIS -->
<img :src="image.thumb">
Alternatively, you can move the dynamic setting of .thumbnail-image and .active from the container div to the img itself.
Problem 3: .active does not target img
The .active class is applied to .thumbnail-image (the img container), but you really want to apply the filter to the img child element, so you'll have to modify your CSS selector to this:
.active > img {
...
}
If you opted to move the dynamic class setting to the img itself (as suggested previously above), you don't have to modify the selector here.
Demo of fix
Vue.component("carousel", {
template: `
<div class="card-carousel" >
<div class="thumbnails">
<div v-for="(image, index) in images"
:key="image.id"
:class="['thumbnail-image', (activeImage == index) ? 'active' : '']"
#click="activateImage(index)">
<img :src="image.thumb" />
</div>
</div>
<div class="containe-carousel">
<span id="textespan"> {{currentImage.text}}</span>
<div class="photoshop-screenshot">
<img :src="currentImage.big" alt="">
</div>
<div class="card-img">
<img :src="currentImage2.big2" alt="">
</div>
</div>
</div>
`,
computed: {
currentImage() {
return this.images[this.activeImage];
},
currentImage2() {
return this.images[this.activeImage];
}
},
data() {
return {
activeImage: 0
};
},
methods: {
activateImage(imageIndex) {
this.activeImage = imageIndex;
}
},
props: ["images"]
});
new Vue({
el: "#app",
data: () => ({
images: [
{
text: "Photoshop",
id: "1",
big: "//placekitten.com/201/201",
big2: "//placekitten.com/201/201",
thumb: "//placekitten.com/201/201"
},
{
text: "Aurocad",
id: "2",
big: "//placekitten.com/202/202",
big2: "//placekitten.com/202/202",
thumb: "//placekitten.com/202/202"
},
{
text: " Counter-Strike",
id: "3",
big: "//placekitten.com/203/203",
big2: "//placekitten.com/203/203",
thumb: "//placekitten.com/203/203"
},
{
text: "League of Legends",
id: "4",
big: "//placekitten.com/204/204",
big2: "//placekitten.com/204/204",
thumb: "//placekitten.com/204/204"
}
]
})
});
.section {
background-color: black;
}
.card-carousel {
user-select: none;
position: relative;
}
.containe-carousel {
padding-top: 5%;
}
.thumbnails {
display: flex;
justify-content: space-evenly;
flex-direction: row;
}
.thumbnail-image {
display: fixed;
align-items: center;
cursor: pointer;
padding: 2px;
}
.thumbnail-image > img {
width: 100%;
height: auto;
transition: all 250ms;
filter: grayscale(100%);
}
.thumbnail-image:selected > img {
box-shadow: 2px 2px 6px 1px rgba(0, 0, 0, 0.5);
visibility: hidden;
filter: none;
}
.card-img {
position: relative;
}
.card-img > img {
margin: 0 auto;
padding-top: 7%;
z-index: 2;
}
/* .photoshop-screenshot {
position: absolute;
z-index: 1;
width: 65%;
left: 50%;
top: 75%;
} */
.active > img {
/* filter: contrast(1000%) invert(100%) sepia(100%) saturate(10000%)
hue-rotate(90deg); */
filter: grayscale(0);
}
#textespan {
text-align: center;
font-size: 300%;
}
.containe-carousel span {
color: white;
font-weight: bold;
}
<script src="https://unpkg.com/vue#2.5.17"></script>
<section class="section" id="app">
<carousel :starting-image="0"
:show-progress-bar="true"
:images="images"></carousel>
</section>
You only need CSS.
.thumbnail-image > img {
filter: grayscale(100%);
-webkit-filter: grayscale(100%);
}
.thumbnail-image > img:active {
filter: grayscale(0%);
-webkit-filter: grayscale(0%);
}
You can create a class without grayscale, and normal tag img with grayscale. Add class without grayscale,color in my example, for the clicked element, and iterate for others images and remove color class. Like this:
function onClick(it) {
const withColor = it.parentElement
.getElementsByClassName('color')[0];
if(withColor)
withColor.classList.remove('color');
it.classList.add( 'color' );
}
#images {
display: flex;
}
img {
margin: 10px;
width: 100px;
height: 100px;
filter: grayscale( 100% );
border: 3px solid transparent;
}
img.color {
filter: grayscale( 0% );
transition: filter 400ms;
border: 3px solid green;
border-radius: 2px
}
<div id="images">
<img src="https://i.stack.imgur.com/MagOw.jpg" class="image" onclick="onClick(this)">
<img src="https://i.stack.imgur.com/MagOw.jpg" class="image" onclick="onClick(this)">
<img src="https://i.stack.imgur.com/MagOw.jpg" class="image" onclick="onClick(this)">
</div>

Vue.js custom select component with v-model

I want to create a custom select component in Vue.js. Since I need specific options styling, I need to create 'select' made of div's etc that looks and acts like a real html select.
Currently I have something like this:
Vue.component('child', {
template: `<div class="component-container" #click="showOptions = !showOptions">
<div class="component__select">
<span class="component__select--name">Select Fruit</span>
<span class="c-arrow-down" v-if="!showOptions"></span>
<span class="c-arrow-up" v-if="showOptions"></span>
</div>
<ul class="component__select-options" v-if="showOptions" >
<li class="select--option" v-for="option in options">
<label> <input type="checkbox" :value="option"/> {{option.name}}</label>
</li>
</ul>
</div>`,
methods: {
selectOption(option) {
this.$emit('option', option)
}
},
data: () => ({
showOptions: false,
}),
props: ['options']
});
var vm = new Vue({
el: '#app',
data: () => ({
options: [
{id: 0, name: 'Apple'},
{id: 1, name: 'Banana'},
{id: 2, name: 'Orange'},
{id: 2, name: 'Strawberry'},
],
selectedFruit: ''
}),
})
.component__select {
height: 38px;
background-color: #F5F7FA;
border: 1px solid #dddddd;
line-height: 38px;
display: grid;
max-width: 500px;
grid-template-columns: 10fr 1fr;
}
.component__select--name {
font-size: 0.8rem;
padding: 0 0 0 25px;
cursor: pointer;
}
.c-arrow-down {
justify-self: end;
}
.component__select-options {
max-height: 180px;
border: 1px solid #dddddd;
border-top: none;
overflow: auto;
position: absolute;
z-index: 1500;
max-width: 500px;
width: 500px;
margin: 0;
padding: 0;
}
.select--option {
height: 35px;
display: grid;
align-content: center;
padding: 0 0 0 25px;
background-color: #f5f5fa;
border-bottom: 1px solid #dddddd;
}
.select--option:last-child {
border-bottom: none;
}
.select--option:nth-child(2n) {
background-color: #ffffff;
}
.select--option input{
display: none;
}
.single-option {
height: 55px;
background-color: #2595ec;
font-size: 0.8rem;
border: 1px solid red;
}
.cust-sel {
width: 200px;
height: 38px;
background-color: #f5f5fa;
border: 1px solid #dddddd;
}
.cust-sel:focus {
outline-width: 0;
}
<html>
<head>
<title>An example</title>
</head>
<body>
<div id="app">
<span> This is parent component</span>
<p>I want to have data from select here: "{{selectedFruit}}"</p>
<child :options="options" v-model="selectedFruit"></child>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
</html>
But my problem is now how to return data from child to parent component using v-model on child component.
(I know I could emit data from child component and do:
<custom-select :options="someOptions" #selected="setSelectedOption"/>
but I need it to be reusable and writing more and more methods to retrieve data from every select in parent component is not exactly how it should work I think.)
Also I need to have an entire object returned, not only ID. (that's why i've got :value="option")
Any ideas?
As Vue Guide said:
v-model is essentially syntax sugar for updating data on user input
events, plus special care for some edge cases.
The syntax sugar will be like:
the directive=v-model will bind value, then listen input event to make change like v-bind:value="val" v-on:input="val = $event.target.value"
So for your use case, you need to create one prop=value, then emit the selected option with event=input.
Like below demo (bind/emit the whole option object):
Vue.config.productionTip = false
Vue.component('child', {
template: `<div class="component-container" #click="showOptions = !showOptions">
<div class="component__select">
<span class="component__select--name">{{value ? value.name : 'Select Fruit'}}</span>
<span class="c-arrow-down" v-if="!showOptions"></span>
<span class="c-arrow-up" v-if="showOptions"></span>
</div>
<ul class="component__select-options" v-if="showOptions" >
<li class="select--option" v-for="option in options" #click="selectOption(option)">
<label> <input type="checkbox" :value="option"/> {{option.name}}</label>
</li>
</ul>
</div>`,
methods: {
selectOption(option) {
this.$emit('input', option)
}
},
data: () => ({
showOptions: false
}),
props: ['options', 'value']
});
var vm = new Vue({
el: '#app',
data: () => ({
options: [
{id: 0, name: 'Apple'},
{id: 1, name: 'Banana'},
{id: 2, name: 'Orange'},
{id: 2, name: 'Strawberry'},
],
selectedFruit: ''
}),
})
.component__select {
height: 38px;
background-color: #F5F7FA;
border: 1px solid #dddddd;
line-height: 38px;
display: grid;
max-width: 500px;
grid-template-columns: 10fr 1fr;
}
.component__select--name {
font-size: 0.8rem;
padding: 0 0 0 25px;
cursor: pointer;
}
.c-arrow-down {
justify-self: end;
}
.component__select-options {
max-height: 180px;
border: 1px solid #dddddd;
border-top: none;
overflow: auto;
position: absolute;
z-index: 1500;
max-width: 500px;
width: 500px;
margin: 0;
padding: 0;
}
.select--option {
height: 35px;
display: grid;
align-content: center;
padding: 0 0 0 25px;
background-color: #f5f5fa;
border-bottom: 1px solid #dddddd;
}
.select--option:last-child {
border-bottom: none;
}
.select--option:nth-child(2n) {
background-color: #ffffff;
}
.select--option input{
display: none;
}
.single-option {
height: 55px;
background-color: #2595ec;
font-size: 0.8rem;
border: 1px solid red;
}
.cust-sel {
width: 200px;
height: 38px;
background-color: #f5f5fa;
border: 1px solid #dddddd;
}
.cust-sel:focus {
outline-width: 0;
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<span> This is parent component</span>
<p>I want to have data from select here: "{{selectedFruit}}"</p>
<child :options="options" v-model="selectedFruit"></child>
</div>
When using v-model on custom component all you need is to declare a prop named 'value' and when you need the component to chance it emit an 'input' event.
Something like this:
<template>
<form #submit.prevent="$emit('onSearch',val)" class="form-perfil">
<div class="form-group col-md-12">
<input v-model="val" #input="$emit('input',val)"
placeholder="filtrar resultados" class="form-control">
</div>
</form>
</template>
<script>
module.exports = {
name: "CaixaFiltro",
props: ["value"],
data: _ => ({ val: "" }),
created() {
this.val = this.value
}
}
</script>
Then you can use (after register the component) it like this:
<caixa-filtro v-model="textoBusca" #onSearch="listar"></caixa-filtro>
You can find more detailed info there:

How to keep flex element's width after removing contents?

I have this flexible layout and some JS https://jsfiddle.net/7k8t3xgc/3/
<div class="window">
<div class="left">
<div class="optional">optional content</div>
</div>
<div class="right">
<div class="wordpool"></div>
<div class="category"></div>
</div>
</div>
The .wordpool element is filled with some words that need to be moved to the .category element by clicking on them.
What is happening now, is that the .window element is shrinking in width when you click the words. Is there a way to prevent this behaviour? Only way I can think of is to calculate wordpools width on render and set it into a style attribute, but it has its drawbacks with responsiveness.
I can't remove the flex functionality, because both left (optional) and right panels need to be same width and centered.
I can't use static width as it needs to be responsive.
It can't be something like .window { width: 90%; } because of short content looking silly on wide screens.
Both left and right content changes between pages in my app (think of a quiz or Google Forms - can be text, can be images, checkboxes, radiobuttons etc.) but the HTML template is the same.
As you want it to be dynamic, based on the actual text width on load, add this line to your script
$(".window").css('min-width', $(".window").width() + 'px');
Updated fiddle
Instead of monitoring the resize event for smaller screens, you can do like this instead
Note, the width: 100% needs to be set using the script, if set in CSS, the calculation will be wrong
$(".window").css({'max-width':$(".window").width() + 'px','width':'100%'});
Updated fiddle 2
Just to provide another solution, that may or not be what you want:
Don't change the elements from container, just have them on both containers, and toggle the opacity.
You can rearrange them using flexbox and order
var buttons = [{
name: "lorem"
},
{
name: "ipsum"
},
{
name: "dolor"
},
{
name: "sit"
},
{
name: "amet"
}
];
$(document).ready(function() {
for (b of buttons) {
$('.wordpool').append($("<span>", {
class: "word",
id: b.name
}).html(b.name));
$('.category').append($("<span>", {
class: "word hidden",
id: b.name
}).html(b.name));
}
$(".wordpool").on("click", "span", function() {
$(this).toggleClass('hidden');
$(".category #" + $(this).attr('id')).toggleClass('hidden');
});
$(".category").on("click", "span", function() {
$(this).toggleClass('hidden');
$(".wordpool #" + $(this).attr('id')).toggleClass('hidden');
});
$("body").on("click", ".showoptional", function() {
$(".left").toggle();
});
});
html,
body {
height: 100%;
margin: 0;
}
.wrapper {
box-sizing: border-box;
width: 100%;
height: 100%;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
background: #f4efdc;
}
.showoptional {
position: absolute;
top: 5px;
left: 5px;
}
.window {
background: #fff;
box-shadow: 0 0 10px #ccc;
display: flex;
}
.left,
.right {
padding: 20px;
flex: 1 0 0px;
}
.left {
display: none;
}
.optional {
background: #eee;
text-align: center;
padding: 50px 0;
}
.word {
display: inline-block;
margin: 2px 5px;
padding: 3px 5px;
border: 1px solid #ddd;
cursor: pointer;
}
.hidden {
opacity: 0;
order: 99;
}
.wordpool {
text-align: center;
display: flex;
}
.category {
margin-top: 10px;
border: 1px solid #ccc;
min-height: 60px;
}
.category .word {
display: block;
text-align: center;
margin: 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<input type="button" class="showoptional" value="Trigger optional content" />
<div class="window">
<div class="left">
<div class="optional">optional content</div>
</div>
<div class="right">
<div class="wordpool"></div>
<div class="category"></div>
</div>
</div>
</div>

equivalent to {'display': ''} within stylesheet

Within Javascript I am able to make a div (a rectangle with a solid border), set its display to none, and then change its display setting back to showing itself using {'display': ''}
Ex:
var overlay = $('<div class="area"></div>')
.css({position: 'absolute', left: l + 'px',
top: t + 'px', border: 'solid', borderColor: 'red', display: 'none' }).
overlay.css({'display': ''});
});
I want to make a CSS class that sets its elements display's back to their defaults:
<style id="default">.default { display: '';}</style>
<div class="default"></div>
This does not work. Can anyone tell me the correct syntax for this?
$('a.show').click(function() {
$('.area').addClass('show');
});
$('a.hide').click(function() {
$('.area').removeClass('show');
});
.area {
position: absolute;
left: lpx;
top: 30px;
display: none;
width: 50px;
height: 50px;
border: 5px solid red;
}
.area.show {
display: block;
}
a {
display: inline-block;
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="area"></div>
<a class="show">SHOW</a>
<a class="hide">HIDE</a>

Categories

Resources