What would be the best way to split a word in the middle (or after a specific amount of characters or syllables) and join both "word-parts" with a line. Basically imagine a very long flexible underscore.
The goal is to have "word___part" always 100% of the parent container.
Meaning it should work fully responsive when scaling down or up the browser-window.
span:first-child {
float:left;
display:inline-block;
}
span.underscore {
}
span:last-child {
float:right;
display:inline-block;
}
<span>Auto</span><span class="underscore"></span><span>mation</span>
How would you approach that? Flexbox?
Additionally the meta-goal would even be to set the word that is split apart with a dynamic-cms. Meaning the word "Automation" comes from a backend.
You can use :after pseudo-element on first span element and set align-items: flex-end; to align line at bottom of spans.
div {
width: 70%;
display: flex;
}
span:first-child {
display: flex;
align-items: flex-end;
flex: 1;
}
span:first-child:after {
content: '';
height: 1px;
background: black;
flex: 1;
}
<div>
<span>Auto</span><span>mation</span>
</div>
<div>
<span>Lorem ipsum dolor </span><span>sit.</span>
</div>
You can also use js to split string at specific word and wrap each part in span elements.
function modify(selector, word) {
var el = document.querySelector(selector);
var text = el.textContent;
var i = text.indexOf(word)
if (i != -1) {
var arr = [text.substring(0, i), text.substring(i)]
el.innerHTML = arr.map(e => '<span>' + e + '</span>').join('');
}
}
modify('.e1', 'mation')
modify('.e2', 'sit')
div {
width: 70%;
display: flex;
}
span:first-child {
display: flex;
align-items: flex-end;
flex: 1;
}
span:first-child:after {
content: '';
height: 1px;
background: black;
flex: 1;
}
<div class="e1">Automation</div>
<div class="e2">Lorem ipsum dolor sit.</div>
Apply border-bottom to .underscore along with flex-grow: 1, then adjust height and margins to fit.
.wrapper {
display: flex;
}
span.underscore {
border-bottom: 2px solid black;
flex-grow: 1;
height: 0.5em;
margin: 0 5px;
}
<div class="wrapper">
<span>Auto</span><span class="underscore"></span><span>mation</span>
</div>
You can even use a dotted border instead of solid to simulate ellipses.
A pretty simple way:
<div>
<span class="left">Auto</span>
<span class="underscore"></span>
<span class="right">mation</span>
</div>
div {
display: flex;
}
.underscore {
width: 100%;
border-bottom: 1px solid #000;
margin: 0 5px;
}
https://codepen.io/anon/pen/XaddqO
In case if background-color behind text element is a solid color:
Create background-image with linear-gradient() on parent.
Override background-color on child elements.
Working Demo:
.text {
background: linear-gradient(to top, transparent 5px, black 5px,
black 7px, transparent 7px);
justify-content: space-between;
display: flex;
}
.text span {
background: #fff;
padding: 0 5px;
}
<div class="text">
<span>Auto</span>
<span>mation</span>
</div>
The answers are good but you said Additionally the meta-goal would even be to set the word that is split apart with a dynamic-cms. Meaning the word "Automation" comes from a backend.
So yiu can use the getword() method to get the word from backend and separate it into two using javascript
You can try to run the snippet and see the output. Then change the string returned by the getword() method and run again.
var container = document.getElementById('slit-container');
var word = getWord();
var wordPartOne = word.substring(0, 4);
var wordPartTwo = word.substring(4, word.lenght);
var data = "<span>"+wordPartOne+"</span> <span>"+wordPartTwo+"</span>";
container.innerHTML = data;
function getWord(){
//Query your backend to get the word
//for test purpose I will just return a string
return "Automation"
}
div {
width: 70%;
display: flex;
}
span:first-child {
display: flex;
align-items: flex-end;
flex: 1;
}
span:first-child:after {
content: '';
height: 1px;
background: black;
flex: 1;
}
<div id="slit-container">
</div>
Related
So I like this, where it wraps but yet the boxes all align on both sides and fill the whole space.
<head>
<style>
* {
padding: 0px;
margin: 0px;
text-transform: none;
font-style: normal;
}
p {
display: flex;
flex-wrap: wrap;
width: 200px;
}
i {
flex: 1;
padding: 5px;
margin: 2px;
background: #ddd;
text-align: center;
}
</style>
</head>
<body>
<p>
<i>foo</i><i>hello</i><i>congratulations</i><i>forward</i><i>interesting</i><i>place</i><i>walk</i><i>to</i><i>anyplace</i><i>next</i><i>sophisticationism</i>
</p>
</body>
Using a mix of small and large words, it somehow figures out how to optimally lay them out so it fills the space completely.
What I would like to do now is, instead of having each box be a dynamically width'd rectangle, I would like for the boxes to "snap to a grid" so to speak. That is, imagine there was a grid of squares that stretched across each row. Sort of like this (which I've completely hardcoded, just for the sake of demonstrating what it looks like. In reality this is what my question is about, how to make this automatic using FlexBox).
<head>
<style>
* {
padding: 0px;
margin: 0px;
text-transform: none;
font-style: normal;
}
p {
display: flex;
flex-wrap: wrap;
width: 220px;
}
i {
width: 50px;
height: 50px;
padding: 5px;
margin: 2px;
background: #ddd;
text-align: center;
}
.l {
width: 114px;
}
</style>
</head>
<body>
<p>
<i>a</i><i>a</i><i>a</i><i>a</i><i class='l'>long</i><i>a</i><i class='l'>long</i><i>a</i><i class='l'>a</i><i class='l'>long</i><i>a</i><i>a</i><i>a</i><i>a</i><i>a</i><i>a</i><i>a</i>
</p>
</body>
So to rephrase, my question is how to cause flowing text (like the words in the images above) layout so (a) it fills each row, and (b) each box is a multiple of a square. That is, it snaps to the grid of a square, weather it's 1, 2, 3+ squares, rather than being 2.5 squares or 1.2345 squares or something. It always snaps to a whole block. It does this by first looking at the longer words, and calculating how many blocks it will take up. Then it stretches any shorter blocks (like the one letter "a" in the example above) so as to fill the blank space.
Wondering how this could be done with FlexBox or otherwise with CSS.
Try (I use split 1-3 words depends on length from here )
function show(n) {
text.innerHTML = '<p>' + split(text.innerText,n).map(line=> {
if(line.length==2 && line[0].length<n && line[1].length<n) {
// case for two short words
return `<i class='long'>${line[0]}</i><i class='short'>${line[1]}</i>`
} else {
return line.map(w=>`<i class='${w.length<9 ?'short':'long'}'>${w}</i>`).join('')
}
}).join('') + '</p>';
}
function split(str,n) {
let z=0, b=[], r=[], w=str.split(' ');
let s = w.map(v => v.length < n ? 1 : 2);
s.map((v,i)=>(
z+v>=4 ? (r.push(b),z=0,b=[]) : 0,
z+=v, b.push(w[i])
))
return b.length ? r.concat([b]) : r;
}
show(9) // 9 is min number of letters for long words;
.short {
flex-basis: 64px;
flex-grow: 1
}
.long {
flex-basis: 140px;
flex-grow: 2
}
* {
padding: 0px;
margin: 0px;
text-transform: none;
font-style: normal;
}
p {
display: flex;
flex-wrap: wrap;
width: 260px;
}
i {
flex: 1;
padding: 5px;
margin: 2px;
background: #ddd;
text-align: center;
}
<div id="text">a aaa foo hello congratulations forward interesting place walk to anyplace next sophisticationism aa bb cccccccccc ddd</div>
I've created a section with one div.
The button 'click' adds new div each time when I click.
What I need: div 1 -> 100% width (section)
when I click:
div 1 and div2 (div 2 new) -> get 50% width each.
click again:
div1, div2 and div3 -> 30% width each.
click again:
div 4 goes to next line with the same width
Do you have any idea?
https://jsfiddle.net/Vova_Champion/tcyw64wq/6/
document.getElementById("button").onclick = function() {
let ok = true;
if (ok === true) {
let div = document.createElement('div');
div.className = 'new-div';
document.getElementsByTagName('section')[0].appendChild(div);
}
};
section {
display: flex;
height: 100px;
width: 200px;
background: red;
flex-wrap: wrap;
overflow: auto;
}
div {
display: block;
height: 30px;
width: 100%;
max-width: 30%;
background: blue;
margin: 5px 2px;
}
#button {
color: red
}
<button id="button">Click button</button>
<section id="section">
<div></div>
</section>
Use this div style:
div {
flex-grow: 1;
display:block;
height: 30px;
min-width: 30%;
background: blue;
margin: 5px 2px;
}
"Flex-grow" gives them "weight" inside the div, items with the same flex grow share the same portion of the available space. Min-width triggers the 4th div to go down since adding that to the same line would make their width 25%.
If you need any further explanation, please ask!
I would also suggest some flex-grow and a conditional class to fix width after 3 items. Here is my try ;)
I have also used css calc.
(function() {
const section = document.getElementById('section');
function addDiv() {
const div = document.createElement('div');
div.className = 'new-div';
section.appendChild(div);
if (section.childNodes.length > 3) {
section.classList.add("fixedWith");
}
}
document.getElementById("button").onclick = function() {
addDiv();
};
document.addEventListener("DOMContentLoaded", function() {
addDiv();
});
})();
section {
display: flex;
height: 100px;
width: 200px;
background: red;
flex-wrap: wrap;
overflow: auto;
}
div {
flex-grow: 1;
min-width: calc(100% / 3 - 4px);
height: 30px;
background: blue;
margin: 5px 2px;
}
section.fixedWith div {
max-width: calc(100% / 3 - 4px);
}
#button {
color: red;
}
<html>
<body>
<button id="button">Click button</button>
<section id="section"></section>
</body>
<html>
Putting flex: 1 on the div says that it will take 1 fraction of the space in its parent. When another div is added, it then takes 1 of the two available fractions of space and so on. The flex-basis: 30%; effectively says that each flex item can take at most 30% of the available space for that row. Hopefully this fixes your problem!
section {
display: flex;
height: 100px;
width: 200px;
background: red;
flex-wrap: wrap;
overflow: auto;
}
div {
display: block;
height: 10px;
flex: 1;
flex-basis: 30%;
background: blue;
margin: 5px 2px;
}
#button {
color: red;
}
I want to set a box with a paragraph in it. The text of this paragraph is supposed to be replaced after every time I click on the button. And what is important to me is that this text should stay inside the box as a one line and not break. To do that I decided to use FitText.js plugin because words have different lengths (given words are just an example). By setting it as a table and table-cell I've achieved a nice align (both vertical and horizontal). Do you have any ideas why given code doesn't work as it should?
var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Bradley"];
var button1 = document.getElementById("give_me_a_name_please");
button1.addEventListener("click", function1);
function getRandomItem(array){
return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
function function1(){
var randomWord = getRandomItem(words);
document.getElementById('word').innerHTML = randomWord;
}
$('#give_me_a_name_please').click(function() {
function resize () { $("#word").fitText(0.6); }
});
#parent_of_word {
width: 20%;
height: 20%;
top: 10%;
left: 10%;
display: flex;
position: absolute;
text-align: center;
justify-content: center;
line-height: 100%;
border: 5px solid black;
word-break: keep-all;
white-space: nowrap;
}
#word {
color: brown;
display:flex;
align-items: center;
justify-content: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
Edit: updated code snippet and JSFiddle with a more optimal loop.
I've adapted your example code to be a bit leaner and easier to understand. It also uses pure jQuery instead of a mix of jQuery and pure JS and won't stop at 'undefined' after pressing the button several times, resulting in an empty array. It will instead cycle through all the words again.
There are two main solutions in effect here.
One takes inspiration from this iterative approach to JavaScript Scale Text to Fit in Fixed Div where the font size starts at a fixed value, then scales down as necessary until the word's width is less than its container's width. No need for a plugin as this is extremely trivial.
The second part implements overflow:hidden so that in the event that the text is so massive that it cannot possibly be shrunk small enough (see the lower limit of 8 in the while-loop), it will still not break out of its container.
See also the JSFiddle version.
var words = [
"Emily",
"William Callum Smith Jr.",
"Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard",
"EdwaaaaaaaaaaaaaaaaaaaAAAAAAAAAaaaaaAAaaaaAAAaaaaaaaaaaaaaaaaaaaaaaaaard",
"Bradley",
"The quick brown fox"
];
var changeWord = $("#change_word");
var parentOfWord = $("#parent_of_word");
var word = $("#word");
var idx = 0;
changeWord.click(function() {
word.text(words[idx++ % words.length]);
var size = 40;
word.css("font-size", size);
while (word.width() > parentOfWord.width() && size > 8) {
word.css("font-size", --size);
}
});
#parent_of_word {
width: 200px;
height: 50%;
top: 50px;
left: 50%;
margin-left: -100px;
display: flex;
position: absolute;
text-align: center;
justify-content: center;
line-height: 100%;
border: 5px solid black;
word-break: keep-all;
white-space: nowrap;
overflow: hidden;
}
#word {
color: brown;
display: flex;
align-items: center;
justify-content: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
<button id="change_word">Button</button>
</p>
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
To have your text in one line, without breaking:
white-space: nowrap;
To center anything vertically and horizontally:
display:flex;
align-items: center;
justify-content: center;
Applied to your example:
var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Resize this to see how it behaves on narrower screens. Lorem ipsum dolor sit amet bla bla bla, lorem ipsum dolor sit amet bla bla bla, lorem ipsum dolor sit amet bla bla bla.", "Bradley"];
var button1 = document.getElementById("give_me_a_name_please");
button1.addEventListener("click", function1);
function getRandomItem(array){
return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
function function1(){
var randomWord = getRandomItem(words) || 'No more options.';
document.getElementById('word').innerHTML = randomWord;
}
$( '#give_me_a_name_please' ).click(function() {
function resize () { $("#word").fitText(0.6);
}
});
#parent_of_word {
display: flex;
align-items: center;
justify-content: center;
/* rest optional, just to demo
* vertical alignment
*/
height: calc(100vh - 40px);
border: 1px solid red;
padding: 1rem;
}
#word {
white-space: nowrap;
border: 5px solid;
padding: 1rem;
flex: 0 1 auto;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
}
* {
margin: 0;
box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
It's because you've defined the width of the #parent_of_word to be 20%, which of course is related to its parent element, i.e. the body element, based on the given example.
So the width of the #parent_of_word can't be just resized dynamically based on the width of its content. It can only be "visually resized" together with its parent width, but still, it will take 20% of it. Even though the used unit are % and the element's width is dynamic, it's still fixed.
So my solution would be to omit the width property and just define the padding of your choice:
Note: I've commented out the unnecessary.
var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Bradley"];
var button1 = document.getElementById("give_me_a_name_please");
button1.addEventListener("click", function1);
function getRandomItem(array) {
return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
function function1() {
var randomWord = getRandomItem(words);
document.getElementById('word').innerHTML = randomWord;
}
$('#give_me_a_name_please').click(function() {
function resize() {
$("#word").fitText(0.6);
}
});
#parent_of_word {
display: flex;
/*width: 20%; the culprit*/
height: 20%;
padding: 0 20px; /* can also use [%] */
position: absolute;
top: 10%;
left: 10%;
/*text-align: center;*/
justify-content: center;
align-items: center; /* added; vertical alignment */
/*line-height: 100%;*/
border: 5px solid black;
/*
word-break: keep-all;
white-space: nowrap;
*/
color: brown;
}
/*
#word {
color: brown;
display: flex;
align-items: center;
justify-content: center;
}
*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>
<button id="give_me_a_name_please">Button</button>
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
Simplest solution to your problem is to change the #parent_of_word's width value to width:auto. This'll have the width automatically adjust depending on the content (auto adjusts depending on the length of the paragraph).
Working example: https://jsfiddle.net/18faLbap/4/
I usually do it by this approach when I want to keep text in a line. especially I grids.
So no matter how long your box is, it will be in one line and when you hover on it, it will bread to lines to be readable.
var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Bradley"];
var button1 = document.getElementById("give_me_a_name_please");
button1.addEventListener("click", function1);
function getRandomItem(array){
return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
function function1(){
var randomWord = getRandomItem(words);
document.getElementById('word').innerHTML = randomWord;
}
$('#give_me_a_name_please').click(function() {
function resize () { $("#word").fitText(0.6); }
});
#parent_of_word {
width: 20%;
top: 10%;
left: 10%;
display: flex;
position: absolute;
text-align: center;
justify-content: center;
line-height: 100%;
border: 5px solid black;
word-break: keep-all;
}
#word {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: brown;
display:flex;
align-items: center;
justify-content: center;
}
#word:hover {
white-space: normal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/davatron5000/FitText.js/0b4183af/jquery.fittext.js"></script>
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
#parent_of_word {
min-width: 20%;
width: auto;
padding: 0px 20px;
}
All I've done here is add on width: auto and set a min-width:20%. This makes the width dynamic when the text updates inside the box. Added in a little padding to make it look nice too. Hope this helps.
Seeing as you already have jQuery on the page, consider using the jquery-textfill plugin:
http://jquery-textfill.github.io/
It will ensure your text fits to your container.
There is a CSS way to fit words in the content
I basically disable the absolute width of your #parent_of_word and change the display to inline-block, so that its width will fit its content. To make it more beautiful, I add padding property. The reduced and improved version of your code is shown below.
var words = ["Emily", "William Callum Smith Jr.", "Edwaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaard", "Bradley"];
var button1 = document.getElementById("give_me_a_name_please");
button1.addEventListener("click", function1);
function getRandomItem(array){
return array.splice(Math.floor(Math.random() * array.length), 1)[0];
}
function function1(){
var randomWord = getRandomItem(words);
document.getElementById('word').innerHTML = randomWord;
}
#parent_of_word {
top: 10%;
left: 10%;
display: inline-block;
position: absolute;
text-align: center;
padding: 10px;
border: 5px solid black;
word-break: keep-all;
}
#word {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
color: brown;
display:flex;
align-items: center;
justify-content: center;
}
#word:hover {
white-space: normal;
}
<div id="parent_of_word">
<p id="word">----------------</p>
</div>
<button id="give_me_a_name_please">Button</button>
So you no longer need the extra JavaScript library now. More knowledge can be found here
I have a container with a fixed width and overflow: auto; set.
It contains multiple items (display: inline-block;), also with fixed dimensions.
So if the container has enough children, the items will wrap around and create a grid-like pattern.
Now I dynamically remove children from the beginning and want to animate the position change of the items that are filling up the freed space and moving up from the start of a line to the end of the line above.
var counter = 1;
document.getElementById("additem").onclick = function() {
var item = document.createElement("div");
item.innerText = counter;
counter++;
document.getElementById('container').appendChild(item);
}
document.getElementById("removeitem").onclick = function() {
document.getElementById('container').removeChild(
document.getElementById('container').children[0]
);
}
#container {
width: 280px;
overflow: auto;
border: 1px solid red;
padding: 5px;
text-align: center;
}
#container > div {
width: 80px;
height: 90px;
border: 1px solid green;
margin: 5px;
display: inline-block;
}
<button id="additem">add item</button>
<button id="removeitem">remove item</button>
<div id="container">
</div>
EDIT: I am also able to use jQuery to accomplish this behaivor.
A reasonably clean solution is to use an inline style that sets the removed element's opacity to 0, accompanied by a transition and a setTimeout timed to run as soon as the transition finishes, effectively fading out the element and then sliding everything else into place. Here's a quick snippet I put together:
var counter = 1;
document.getElementById("additem").onclick = function() {
var item = document.createElement("div");
item.innerText = counter;
counter++;
document.getElementById('container').appendChild(item);
}
document.getElementById("removeitem").onclick = function() {
document.getElementById('container').children[0].setAttribute('style', 'opacity: 0');
window.setTimeout(function() {
document.getElementById('container').removeChild(
document.getElementById('container').children[0]
)
}, 300);
}
#container {
width: 280px;
overflow: auto;
border: 1px solid red;
padding: 5px;
text-align: center;
}
#container>div {
width: 80px;
height: 90px;
border: 1px solid green;
margin: 5px;
display: inline-block;
transition: opacity 0.3s;
}
<button id="additem">add item</button>
<button id="removeitem">remove item</button>
<div id="container">
</div>
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>